2019-11-20 16:21:32 +00:00
|
|
|
//-------------------------------------------------------------------------
|
|
|
|
/*
|
|
|
|
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
|
|
|
Copyright (C) 2019 sirlemonhead, Nuke.YKT
|
|
|
|
This file is part of PCExhumed.
|
|
|
|
PCExhumed is free software; you can redistribute it and/or
|
|
|
|
modify it under the terms of the GNU General Public License version 2
|
|
|
|
as published by the Free Software Foundation.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
See the GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program; if not, write to the Free Software
|
|
|
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
*/
|
|
|
|
//-------------------------------------------------------------------------
|
2019-11-22 23:11:37 +00:00
|
|
|
#include "ns.h"
|
2020-08-18 07:52:08 +00:00
|
|
|
#include "aistuff.h"
|
2019-08-26 03:59:14 +00:00
|
|
|
#include "exhumed.h"
|
|
|
|
#include "engine.h"
|
|
|
|
#include "sequence.h"
|
|
|
|
#include "player.h"
|
2019-09-21 15:47:55 +00:00
|
|
|
#include "sound.h"
|
2019-11-16 22:32:12 +00:00
|
|
|
#include "names.h"
|
2019-08-26 03:59:14 +00:00
|
|
|
#include <assert.h>
|
|
|
|
|
2019-11-22 23:11:37 +00:00
|
|
|
BEGIN_PS_NS
|
|
|
|
|
2020-10-11 11:14:32 +00:00
|
|
|
enum
|
|
|
|
{
|
2021-10-15 20:55:03 +00:00
|
|
|
kMaxQueens = 1,
|
|
|
|
kMaxEggs = 10,
|
|
|
|
kMaxTails = 7
|
2020-10-11 11:14:32 +00:00
|
|
|
};
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2020-10-11 09:33:28 +00:00
|
|
|
static actionSeq QueenSeq[] = {
|
2020-03-02 21:08:31 +00:00
|
|
|
{0, 0},
|
|
|
|
{0, 0},
|
|
|
|
{9, 0},
|
|
|
|
{36, 0},
|
|
|
|
{18, 0},
|
|
|
|
{27, 0},
|
|
|
|
{45, 0},
|
|
|
|
{45, 0},
|
|
|
|
{54, 1},
|
|
|
|
{53, 1},
|
|
|
|
{55, 1}
|
2019-08-26 03:59:14 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static actionSeq HeadSeq[] = {
|
2020-03-02 21:08:31 +00:00
|
|
|
{56, 1},
|
|
|
|
{65, 0},
|
|
|
|
{65, 0},
|
|
|
|
{65, 0},
|
|
|
|
{65, 0},
|
|
|
|
{65, 0},
|
|
|
|
{74, 0},
|
|
|
|
{82, 0},
|
|
|
|
{90, 0}
|
2019-08-26 03:59:14 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static actionSeq EggSeq[] = {
|
2020-03-02 21:08:31 +00:00
|
|
|
{19, 1},
|
|
|
|
{18, 1},
|
|
|
|
{0, 0},
|
|
|
|
{9, 0},
|
|
|
|
{23, 1},
|
2019-08-26 03:59:14 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct Queen
|
|
|
|
{
|
2021-12-07 17:53:02 +00:00
|
|
|
TObjPtr<DExhumedActor*> pActor;
|
|
|
|
TObjPtr<DExhumedActor*> pTarget;
|
2021-11-21 18:24:46 +00:00
|
|
|
int16_t nHealth;
|
|
|
|
int16_t nFrame;
|
|
|
|
int16_t nAction;
|
|
|
|
int16_t nAction2;
|
|
|
|
int16_t nIndex;
|
|
|
|
int16_t nIndex2;
|
|
|
|
int16_t nChannel;
|
2019-08-26 03:59:14 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct Egg
|
|
|
|
{
|
2021-12-07 17:53:02 +00:00
|
|
|
TObjPtr<DExhumedActor*> pActor;
|
|
|
|
TObjPtr<DExhumedActor*> pTarget;
|
2021-11-21 18:24:46 +00:00
|
|
|
int16_t nHealth;
|
|
|
|
int16_t nFrame;
|
|
|
|
int16_t nAction;
|
|
|
|
int16_t nRun;
|
|
|
|
int16_t nCounter;
|
2019-08-26 03:59:14 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct Head
|
|
|
|
{
|
2021-12-07 17:53:02 +00:00
|
|
|
TObjPtr<DExhumedActor*> pActor;
|
|
|
|
TObjPtr<DExhumedActor*> pTarget;
|
2021-11-21 18:24:46 +00:00
|
|
|
int16_t nHealth;
|
|
|
|
int16_t nFrame;
|
|
|
|
int16_t nAction;
|
|
|
|
int16_t nRun;
|
|
|
|
int16_t nIndex;
|
|
|
|
int16_t nIndex2;
|
|
|
|
int16_t nChannel;
|
2019-08-26 03:59:14 +00:00
|
|
|
};
|
|
|
|
|
2020-11-29 23:40:25 +00:00
|
|
|
FreeListArray<Egg, kMaxEggs> QueenEgg;
|
|
|
|
|
2021-11-21 18:24:46 +00:00
|
|
|
int QueenCount = 0;
|
2020-11-29 23:40:25 +00:00
|
|
|
int nQHead = 0;
|
2021-11-21 18:24:46 +00:00
|
|
|
int nHeadVel;
|
|
|
|
int nVelShift;
|
2020-11-29 23:40:25 +00:00
|
|
|
|
2021-12-07 17:53:02 +00:00
|
|
|
TObjPtr<DExhumedActor*> tailspr[kMaxTails];
|
2020-11-29 23:40:25 +00:00
|
|
|
|
|
|
|
|
2019-08-26 03:59:14 +00:00
|
|
|
Queen QueenList[kMaxQueens];
|
|
|
|
Head QueenHead;
|
|
|
|
|
|
|
|
int MoveQX[25];
|
|
|
|
int MoveQY[25];
|
|
|
|
int MoveQZ[25];
|
2021-11-23 00:15:28 +00:00
|
|
|
sectortype* MoveQS[25];
|
2021-11-21 18:24:46 +00:00
|
|
|
int16_t MoveQA[25];
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2021-12-07 17:53:02 +00:00
|
|
|
|
|
|
|
size_t MarkQueen()
|
|
|
|
{
|
|
|
|
GC::Mark(QueenList[0].pActor);
|
|
|
|
GC::Mark(QueenList[0].pTarget);
|
|
|
|
GC::Mark(QueenHead.pActor);
|
|
|
|
GC::Mark(QueenHead.pTarget);
|
|
|
|
for (int i = 0; i < kMaxEggs; i++)
|
|
|
|
{
|
|
|
|
GC::Mark(QueenEgg[i].pActor);
|
|
|
|
GC::Mark(QueenEgg[i].pTarget);
|
|
|
|
}
|
|
|
|
return 4 + 2 * kMaxEggs;
|
|
|
|
}
|
|
|
|
|
2020-11-29 23:40:25 +00:00
|
|
|
FSerializer& Serialize(FSerializer& arc, const char* keyname, Queen& w, Queen* def)
|
|
|
|
{
|
|
|
|
if (arc.BeginObject(keyname))
|
|
|
|
{
|
|
|
|
arc("health", w.nHealth)
|
|
|
|
("frame", w.nFrame)
|
|
|
|
("action", w.nAction)
|
2021-10-26 19:10:51 +00:00
|
|
|
("sprite", w.pActor)
|
|
|
|
("target", w.pTarget)
|
2021-10-20 09:20:49 +00:00
|
|
|
("ata", w.nAction2)
|
|
|
|
("atc", w.nIndex)
|
|
|
|
("at10", w.nIndex2)
|
2020-11-29 23:40:25 +00:00
|
|
|
.EndObject();
|
|
|
|
}
|
|
|
|
return arc;
|
|
|
|
}
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2020-11-29 23:40:25 +00:00
|
|
|
FSerializer& Serialize(FSerializer& arc, const char* keyname, Egg& w, Egg* def)
|
|
|
|
{
|
|
|
|
if (arc.BeginObject(keyname))
|
|
|
|
{
|
|
|
|
arc("health", w.nHealth)
|
|
|
|
("frame", w.nFrame)
|
|
|
|
("action", w.nAction)
|
2021-10-26 18:13:03 +00:00
|
|
|
("sprite", w.pActor)
|
|
|
|
("target", w.pTarget)
|
2021-10-20 09:20:49 +00:00
|
|
|
("runptr", w.nRun)
|
|
|
|
("atc", w.nCounter)
|
2020-11-29 23:40:25 +00:00
|
|
|
.EndObject();
|
|
|
|
}
|
|
|
|
return arc;
|
|
|
|
}
|
2019-12-26 21:00:04 +00:00
|
|
|
|
2020-11-29 23:40:25 +00:00
|
|
|
FSerializer& Serialize(FSerializer& arc, const char* keyname, Head& w, Head* def)
|
|
|
|
{
|
|
|
|
if (arc.BeginObject(keyname))
|
|
|
|
{
|
|
|
|
arc("health", w.nHealth)
|
|
|
|
("frame", w.nFrame)
|
|
|
|
("action", w.nAction)
|
2021-10-26 17:55:20 +00:00
|
|
|
("sprite", w.pActor)
|
|
|
|
("target", w.pTarget)
|
2021-10-20 09:20:49 +00:00
|
|
|
("at8", w.nRun)
|
|
|
|
("atc", w.nIndex)
|
|
|
|
("tails", w.nIndex2)
|
2020-11-29 23:40:25 +00:00
|
|
|
.EndObject();
|
|
|
|
}
|
|
|
|
return arc;
|
|
|
|
}
|
2019-12-26 21:00:04 +00:00
|
|
|
|
2020-11-29 23:40:25 +00:00
|
|
|
void SerializeQueen(FSerializer& arc)
|
|
|
|
{
|
|
|
|
if (arc.BeginObject("queen"))
|
|
|
|
{
|
|
|
|
arc("count", QueenCount);
|
|
|
|
if (QueenCount == 0) // only save the rest if we got a queen. There can only be one.
|
|
|
|
{
|
2021-03-09 21:18:43 +00:00
|
|
|
for (int i = 0; i < kMaxEggs; i++)
|
|
|
|
{
|
2021-10-20 09:20:49 +00:00
|
|
|
QueenEgg[i].nRun = -1;
|
2021-03-09 21:18:43 +00:00
|
|
|
}
|
2020-11-29 23:40:25 +00:00
|
|
|
arc("qhead", nQHead)
|
|
|
|
("headvel", nHeadVel)
|
|
|
|
("velshift", nVelShift)
|
|
|
|
("head", QueenHead)
|
|
|
|
.Array("tailspr", tailspr, countof(tailspr))
|
|
|
|
("queen", QueenList[0])
|
|
|
|
("eggs", QueenEgg)
|
|
|
|
.Array("moveqx", MoveQX, countof(MoveQX))
|
|
|
|
.Array("moveqy", MoveQY, countof(MoveQY))
|
|
|
|
.Array("moveqz", MoveQZ, countof(MoveQZ))
|
|
|
|
.Array("moveqa", MoveQA, countof(MoveQA))
|
|
|
|
.Array("moveqs", MoveQS, countof(MoveQS));
|
|
|
|
}
|
|
|
|
arc.EndObject();
|
|
|
|
}
|
|
|
|
}
|
2019-12-26 21:00:04 +00:00
|
|
|
|
2019-08-26 03:59:14 +00:00
|
|
|
void InitQueens()
|
|
|
|
{
|
2019-08-31 07:47:15 +00:00
|
|
|
QueenCount = 1;
|
2020-11-29 23:40:25 +00:00
|
|
|
QueenEgg.Clear();
|
2019-08-31 07:47:15 +00:00
|
|
|
for (int i = 0; i < kMaxEggs; i++)
|
|
|
|
{
|
2021-10-20 09:20:49 +00:00
|
|
|
QueenEgg[i].nRun = -1;
|
2019-08-31 07:47:15 +00:00
|
|
|
}
|
2019-08-26 03:59:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int GrabEgg()
|
|
|
|
{
|
2020-11-29 23:40:25 +00:00
|
|
|
auto egg = QueenEgg.Get();
|
|
|
|
if (egg == -1) return -1;
|
|
|
|
return egg;
|
2019-08-26 03:59:14 +00:00
|
|
|
}
|
|
|
|
|
2021-10-26 19:10:51 +00:00
|
|
|
void BlowChunks(DExhumedActor* pActor)
|
2019-08-26 03:59:14 +00:00
|
|
|
{
|
2019-08-31 07:47:15 +00:00
|
|
|
for (int i = 0; i < 4; i++)
|
|
|
|
{
|
2021-10-26 19:15:07 +00:00
|
|
|
BuildCreatureChunk(pActor, seq_GetSeqPicnum(16, i + 41, 0));
|
2019-08-31 07:47:15 +00:00
|
|
|
}
|
2019-08-26 03:59:14 +00:00
|
|
|
}
|
|
|
|
|
2021-11-21 19:34:15 +00:00
|
|
|
void DestroyEgg(int nEgg)
|
2019-08-26 03:59:14 +00:00
|
|
|
{
|
2021-12-07 17:53:02 +00:00
|
|
|
DExhumedActor* pActor = QueenEgg[nEgg].pActor;
|
|
|
|
if (!pActor) return;
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2019-11-17 18:48:56 +00:00
|
|
|
if (QueenEgg[nEgg].nAction != 4)
|
|
|
|
{
|
2022-01-31 22:33:44 +00:00
|
|
|
BuildAnim(nullptr, 34, 0, pActor->int_pos().X, pActor->int_pos().Y, pActor->int_pos().Z, pActor->sector(), pActor->spr.xrepeat, 4);
|
2019-11-17 18:48:56 +00:00
|
|
|
}
|
|
|
|
else
|
2019-08-31 07:47:15 +00:00
|
|
|
{
|
|
|
|
for (int i = 0; i < 4; i++)
|
|
|
|
{
|
2021-10-26 19:15:07 +00:00
|
|
|
BuildCreatureChunk(pActor, seq_GetSeqPicnum(kSeqQueenEgg, (i % 2) + 24, 0));
|
2019-08-31 07:47:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-23 22:30:41 +00:00
|
|
|
runlist_DoSubRunRec(pActor->spr.intowner);
|
2021-12-23 16:05:44 +00:00
|
|
|
runlist_DoSubRunRec(pActor->spr.lotag - 1);
|
2021-10-20 09:20:49 +00:00
|
|
|
runlist_SubRunRec(QueenEgg[nEgg].nRun);
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-10-20 09:20:49 +00:00
|
|
|
QueenEgg[nEgg].nRun = -1;
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-10-26 18:13:03 +00:00
|
|
|
DeleteActor(pActor);
|
2020-11-29 23:40:25 +00:00
|
|
|
QueenEgg.Release(nEgg);
|
2019-08-26 03:59:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void DestroyAllEggs()
|
|
|
|
{
|
2019-08-31 07:47:15 +00:00
|
|
|
for (int i = 0; i < kMaxEggs; i++)
|
|
|
|
{
|
2021-10-20 09:20:49 +00:00
|
|
|
if (QueenEgg[i].nRun > -1)
|
2019-08-31 07:47:15 +00:00
|
|
|
{
|
|
|
|
DestroyEgg(i);
|
|
|
|
}
|
|
|
|
}
|
2019-08-26 03:59:14 +00:00
|
|
|
}
|
|
|
|
|
2021-10-26 17:55:20 +00:00
|
|
|
void SetHeadVel(DExhumedActor* pActor)
|
2019-08-26 03:59:14 +00:00
|
|
|
{
|
2021-12-23 16:05:44 +00:00
|
|
|
int nAngle = pActor->spr.ang;
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-12-23 16:05:44 +00:00
|
|
|
pActor->spr.xvel = bcos(nAngle, nVelShift);
|
|
|
|
pActor->spr.yvel = bsin(nAngle, nVelShift);
|
2019-08-26 03:59:14 +00:00
|
|
|
}
|
|
|
|
|
2021-10-26 18:52:25 +00:00
|
|
|
Collision QueenAngleChase(DExhumedActor* pActor, DExhumedActor* pActor2, int val1, int val2)
|
2019-08-26 03:59:14 +00:00
|
|
|
{
|
2021-11-16 17:41:34 +00:00
|
|
|
int nAngle;
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2021-10-26 18:52:25 +00:00
|
|
|
if (pActor2 == nullptr)
|
2019-08-31 07:47:15 +00:00
|
|
|
{
|
2021-12-23 16:05:44 +00:00
|
|
|
pActor->spr.zvel = 0;
|
|
|
|
nAngle = pActor->spr.ang;
|
2019-08-31 07:47:15 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-12-23 18:05:20 +00:00
|
|
|
int nTileY = (tileHeight(pActor2->spr.picnum) * pActor2->spr.yrepeat) * 2;
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2022-01-31 22:33:44 +00:00
|
|
|
int nMyAngle = GetMyAngle(pActor2->int_pos().X - pActor->int_pos().X, pActor2->int_pos().Y - pActor->int_pos().Y);
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2022-01-31 22:33:44 +00:00
|
|
|
int edx = ((pActor2->int_pos().Z - nTileY) - pActor->int_pos().Z) >> 8;
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2022-01-31 22:33:44 +00:00
|
|
|
uint32_t xDiff = abs(pActor2->int_pos().X - pActor->int_pos().X);
|
|
|
|
uint32_t yDiff = abs(pActor2->int_pos().Y - pActor->int_pos().Y);
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2020-06-22 10:24:21 +00:00
|
|
|
uint32_t sqrtVal = xDiff * xDiff + yDiff * yDiff;
|
|
|
|
|
|
|
|
if (sqrtVal > INT_MAX)
|
|
|
|
{
|
2020-09-08 16:48:18 +00:00
|
|
|
DPrintf(DMSG_WARNING, "%s %d: overflow\n", __func__, __LINE__);
|
2020-06-22 10:24:21 +00:00
|
|
|
sqrtVal = INT_MAX;
|
|
|
|
}
|
|
|
|
|
|
|
|
int nSqrt = ksqrt(sqrtVal);
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
int var_14 = GetMyAngle(nSqrt, edx);
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2021-12-23 16:05:44 +00:00
|
|
|
int nAngDelta = AngleDelta(pActor->spr.ang, nMyAngle, 1024);
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2021-01-04 12:02:00 +00:00
|
|
|
if (abs(nAngDelta) > 127)
|
2019-08-31 07:47:15 +00:00
|
|
|
{
|
2021-10-15 20:55:03 +00:00
|
|
|
val1 /= abs(nAngDelta >> 7);
|
2019-11-17 18:48:56 +00:00
|
|
|
if (val1 < 256)
|
2019-08-31 07:47:15 +00:00
|
|
|
val1 = 256;
|
|
|
|
}
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2021-01-04 12:02:00 +00:00
|
|
|
if (abs(nAngDelta) > val2)
|
2019-08-31 07:47:15 +00:00
|
|
|
{
|
2019-11-17 18:48:56 +00:00
|
|
|
if (nAngDelta < 0)
|
|
|
|
nAngDelta = -val2;
|
2019-08-31 07:47:15 +00:00
|
|
|
else
|
2019-11-17 18:48:56 +00:00
|
|
|
nAngDelta = val2;
|
2019-08-31 07:47:15 +00:00
|
|
|
}
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2021-12-23 16:05:44 +00:00
|
|
|
nAngle = (nAngDelta + pActor->spr.ang) & kAngleMask;
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2021-12-23 16:05:44 +00:00
|
|
|
pActor->spr.zvel = (AngleDelta(pActor->spr.zvel, var_14, 24) + pActor->spr.zvel) & kAngleMask;
|
2019-08-31 07:47:15 +00:00
|
|
|
}
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2021-12-23 16:05:44 +00:00
|
|
|
pActor->spr.ang = nAngle;
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2021-12-23 16:05:44 +00:00
|
|
|
int da = pActor->spr.zvel;
|
2021-01-04 12:02:00 +00:00
|
|
|
int x = abs(bcos(da));
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2020-11-14 08:45:08 +00:00
|
|
|
int v26 = x * ((val1 * bcos(nAngle)) >> 14);
|
|
|
|
int v27 = x * ((val1 * bsin(nAngle)) >> 14);
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2021-01-04 12:02:00 +00:00
|
|
|
uint32_t xDiff = abs((int32_t)(v26 >> 8));
|
|
|
|
uint32_t yDiff = abs((int32_t)(v27 >> 8));
|
2020-06-22 10:24:21 +00:00
|
|
|
|
|
|
|
uint32_t sqrtNum = xDiff * xDiff + yDiff * yDiff;
|
|
|
|
|
|
|
|
if (sqrtNum > INT_MAX)
|
|
|
|
{
|
2020-09-08 16:48:18 +00:00
|
|
|
DPrintf(DMSG_WARNING, "%s %d: overflow\n", __func__, __LINE__);
|
2020-06-22 10:24:21 +00:00
|
|
|
sqrtNum = INT_MAX;
|
|
|
|
}
|
|
|
|
|
2020-11-14 08:45:08 +00:00
|
|
|
int nSqrt = ksqrt(sqrtNum) * bsin(da);
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2021-10-26 18:52:25 +00:00
|
|
|
return movesprite(pActor, v26 >> 2, v27 >> 2, bsin(bobangle, -5) + (nSqrt >> 13), 0, 0, CLIPMASK1);
|
2019-08-26 03:59:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int DestroyTailPart()
|
|
|
|
{
|
2021-10-20 09:20:49 +00:00
|
|
|
if (!QueenHead.nIndex2) {
|
2019-08-31 07:47:15 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2021-12-07 17:53:02 +00:00
|
|
|
DExhumedActor* pActor = tailspr[--QueenHead.nIndex2];
|
|
|
|
if (!pActor) return 0;
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2021-10-26 19:10:51 +00:00
|
|
|
BlowChunks(pActor);
|
|
|
|
BuildExplosion(pActor);
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2019-08-31 07:47:15 +00:00
|
|
|
for (int i = 0; i < 5; i++)
|
|
|
|
{
|
2021-11-21 18:24:46 +00:00
|
|
|
int nHeight = GetActorHeight(pActor);
|
2021-10-26 19:10:51 +00:00
|
|
|
BuildLavaLimb(pActor, i, nHeight);
|
2019-08-31 07:47:15 +00:00
|
|
|
}
|
2019-08-26 03:59:14 +00:00
|
|
|
|
2021-10-26 19:10:51 +00:00
|
|
|
DeleteActor(pActor);
|
2019-08-31 07:47:15 +00:00
|
|
|
return 1;
|
2019-08-26 03:59:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void BuildTail()
|
|
|
|
{
|
2021-12-23 15:44:43 +00:00
|
|
|
auto head = QueenHead.pActor;
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2022-01-31 22:33:44 +00:00
|
|
|
int x = head->int_pos().X;
|
|
|
|
int y = head->int_pos().Y;
|
|
|
|
int z = head->int_pos().Z;
|
2021-12-30 15:51:56 +00:00
|
|
|
auto pSector =head->sector();
|
2019-08-31 07:47:15 +00:00
|
|
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < kMaxTails; i++)
|
|
|
|
{
|
2021-11-23 00:15:28 +00:00
|
|
|
auto pTailActor = insertActor(pSector, 121);
|
2021-10-26 19:10:51 +00:00
|
|
|
tailspr[i] = pTailActor;
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-12-23 18:05:20 +00:00
|
|
|
pTailActor->spr.lotag = runlist_HeadRun() + 1;
|
2022-05-23 22:30:41 +00:00
|
|
|
pTailActor->spr.intowner = runlist_AddRunRec(pTailActor->spr.lotag - 1, (i + 1), 0x1B0000);
|
2021-12-23 18:05:20 +00:00
|
|
|
pTailActor->spr.shade = -12;
|
2022-01-31 19:03:22 +00:00
|
|
|
pTailActor->set_int_xy(x, y);
|
2021-12-23 18:05:20 +00:00
|
|
|
pTailActor->spr.hitag = 0;
|
|
|
|
pTailActor->spr.cstat = 0;
|
|
|
|
pTailActor->spr.clipdist = 100;
|
|
|
|
pTailActor->spr.xrepeat = 80;
|
|
|
|
pTailActor->spr.yrepeat = 80;
|
|
|
|
pTailActor->spr.picnum = 1;
|
2021-12-30 15:51:56 +00:00
|
|
|
pTailActor->spr.pal = pTailActor->sector()->ceilingpal;
|
2021-12-23 18:05:20 +00:00
|
|
|
pTailActor->spr.xoffset = 0;
|
|
|
|
pTailActor->spr.yoffset = 0;
|
2022-01-31 19:03:22 +00:00
|
|
|
pTailActor->set_int_z(z);
|
2021-12-23 18:05:20 +00:00
|
|
|
pTailActor->spr.extra = -1;
|
2019-08-31 07:47:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < 24 + 1; i++)
|
|
|
|
{
|
|
|
|
MoveQX[i] = x;
|
|
|
|
MoveQZ[i] = z;
|
|
|
|
MoveQY[i] = y;
|
2021-11-23 00:15:28 +00:00
|
|
|
assert(pSector);
|
|
|
|
MoveQS[i] = pSector;
|
2019-08-31 07:47:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
nQHead = 0;
|
2021-10-20 09:20:49 +00:00
|
|
|
QueenHead.nIndex2 = 7;
|
2019-08-26 03:59:14 +00:00
|
|
|
}
|
|
|
|
|
2021-11-21 18:24:46 +00:00
|
|
|
void BuildQueenEgg(int nQueen, int nVal)
|
2019-08-26 03:59:14 +00:00
|
|
|
{
|
2019-08-31 07:47:15 +00:00
|
|
|
int nEgg = GrabEgg();
|
|
|
|
if (nEgg < 0) {
|
2021-10-15 16:37:39 +00:00
|
|
|
return;
|
2019-08-31 07:47:15 +00:00
|
|
|
}
|
|
|
|
|
2021-12-07 17:53:02 +00:00
|
|
|
DExhumedActor* pActor = QueenList[nQueen].pActor;
|
|
|
|
if (!pActor) return;
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2022-01-31 22:33:44 +00:00
|
|
|
int x = pActor->int_pos().X;
|
|
|
|
int y = pActor->int_pos().Y;
|
2021-12-30 15:51:56 +00:00
|
|
|
auto pSector =pActor->sector();
|
2021-11-22 23:55:46 +00:00
|
|
|
int nFloorZ = pSector->floorz;
|
2021-12-23 16:05:44 +00:00
|
|
|
int nAngle = pActor->spr.ang;
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-11-22 23:55:46 +00:00
|
|
|
auto pActor2 = insertActor(pSector, 121);
|
2021-12-23 18:05:20 +00:00
|
|
|
|
2022-01-31 19:03:22 +00:00
|
|
|
pActor2->set_int_pos({ x, y, nFloorZ });
|
2021-12-23 18:05:20 +00:00
|
|
|
pActor2->spr.pal = 0;
|
|
|
|
pActor2->spr.clipdist = 50;
|
|
|
|
pActor2->spr.xoffset = 0;
|
|
|
|
pActor2->spr.yoffset = 0;
|
|
|
|
pActor2->spr.shade = -12;
|
|
|
|
pActor2->spr.picnum = 1;
|
|
|
|
pActor2->spr.ang = (RandomSize(9) + (nAngle - 256)) & kAngleMask;
|
2021-12-30 16:10:08 +00:00
|
|
|
pActor2->backuppos();
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2019-11-17 18:48:56 +00:00
|
|
|
if (!nVal)
|
|
|
|
{
|
2021-12-23 18:05:20 +00:00
|
|
|
pActor2->spr.xrepeat = 30;
|
|
|
|
pActor2->spr.yrepeat = 30;
|
|
|
|
pActor2->spr.xvel = bcos(pActor2->spr.ang);
|
|
|
|
pActor2->spr.yvel = bsin(pActor2->spr.ang);
|
|
|
|
pActor2->spr.zvel = -6000;
|
|
|
|
pActor2->spr.cstat = 0;
|
2019-11-17 18:48:56 +00:00
|
|
|
}
|
|
|
|
else
|
2019-08-31 07:47:15 +00:00
|
|
|
{
|
2021-12-23 18:05:20 +00:00
|
|
|
pActor2->spr.xrepeat = 60;
|
|
|
|
pActor2->spr.yrepeat = 60;
|
|
|
|
pActor2->spr.xvel = 0;
|
|
|
|
pActor2->spr.yvel = 0;
|
|
|
|
pActor2->spr.zvel = -2000;
|
|
|
|
pActor2->spr.cstat = CSTAT_SPRITE_BLOCK_ALL;
|
2019-08-31 07:47:15 +00:00
|
|
|
}
|
|
|
|
|
2021-12-23 18:05:20 +00:00
|
|
|
pActor2->spr.lotag = runlist_HeadRun() + 1;
|
|
|
|
pActor2->spr.extra = -1;
|
|
|
|
pActor2->spr.hitag = 0;
|
2019-08-31 07:47:15 +00:00
|
|
|
|
|
|
|
GrabTimeSlot(3);
|
|
|
|
|
|
|
|
QueenEgg[nEgg].nHealth = 200;
|
2020-11-29 23:40:25 +00:00
|
|
|
QueenEgg[nEgg].nFrame = 0;
|
2021-10-26 18:13:03 +00:00
|
|
|
QueenEgg[nEgg].pActor = pActor2;
|
2021-10-26 19:10:51 +00:00
|
|
|
QueenEgg[nEgg].pTarget = QueenList[nQueen].pTarget;
|
2019-08-31 07:47:15 +00:00
|
|
|
|
|
|
|
if (nVal)
|
|
|
|
{
|
|
|
|
nVal = 4;
|
2021-10-20 09:20:49 +00:00
|
|
|
QueenEgg[nEgg].nCounter = 200;
|
2019-08-31 07:47:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
QueenEgg[nEgg].nAction = nVal;
|
|
|
|
|
2022-05-23 22:30:41 +00:00
|
|
|
pActor2->spr.intowner = runlist_AddRunRec(pActor2->spr.lotag - 1, nEgg, 0x1D0000);
|
2021-10-20 09:20:49 +00:00
|
|
|
QueenEgg[nEgg].nRun = runlist_AddRunRec(NewRun, nEgg, 0x1D0000);
|
2019-08-26 03:59:14 +00:00
|
|
|
}
|
|
|
|
|
2021-10-15 20:55:03 +00:00
|
|
|
void AIQueenEgg::Tick(RunListEvent* ev)
|
2019-08-26 03:59:14 +00:00
|
|
|
{
|
2021-11-21 18:24:46 +00:00
|
|
|
int nEgg = RunData[ev->nRun].nObjIndex;
|
2021-10-15 20:55:03 +00:00
|
|
|
Egg* pEgg = &QueenEgg[nEgg];
|
2021-12-07 17:53:02 +00:00
|
|
|
DExhumedActor* pActor = pEgg->pActor;
|
|
|
|
if (!pActor) return;
|
2021-11-21 18:24:46 +00:00
|
|
|
int nAction = pEgg->nAction;
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-10-26 18:13:03 +00:00
|
|
|
DExhumedActor* pTarget = nullptr;
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2020-03-02 21:08:31 +00:00
|
|
|
bool bVal = false;
|
|
|
|
|
2021-10-15 20:55:03 +00:00
|
|
|
if (pEgg->nHealth <= 0)
|
|
|
|
{
|
|
|
|
DestroyEgg(nEgg);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (nAction == 0 || nAction == 4) {
|
2021-10-26 18:13:03 +00:00
|
|
|
Gravity(pActor);
|
2021-10-15 20:55:03 +00:00
|
|
|
}
|
|
|
|
|
2021-11-21 18:24:46 +00:00
|
|
|
int nSeq = SeqOffsets[kSeqQueenEgg] + EggSeq[nAction].a;
|
2021-10-15 20:55:03 +00:00
|
|
|
|
2021-12-23 16:05:44 +00:00
|
|
|
pActor->spr.picnum = seq_GetSeqPicnum2(nSeq, pEgg->nFrame);
|
2021-10-15 20:55:03 +00:00
|
|
|
|
|
|
|
if (nAction != 4)
|
2019-08-31 07:47:15 +00:00
|
|
|
{
|
2021-10-26 18:13:03 +00:00
|
|
|
seq_MoveSequence(pActor, nSeq, pEgg->nFrame);
|
2021-10-15 20:55:03 +00:00
|
|
|
|
|
|
|
pEgg->nFrame++;
|
|
|
|
if (pEgg->nFrame >= SeqSize[nSeq])
|
2020-03-02 21:08:31 +00:00
|
|
|
{
|
2021-10-15 20:55:03 +00:00
|
|
|
pEgg->nFrame = 0;
|
|
|
|
bVal = true;
|
|
|
|
}
|
|
|
|
|
2021-12-07 17:53:02 +00:00
|
|
|
DExhumedActor* enemy = pEgg->pActor;
|
|
|
|
pTarget = UpdateEnemy(&enemy);
|
|
|
|
pEgg->pActor = enemy;
|
2021-10-26 18:13:03 +00:00
|
|
|
pEgg->pTarget = pTarget;
|
2021-10-15 20:55:03 +00:00
|
|
|
|
2021-12-21 22:18:23 +00:00
|
|
|
if (pTarget && (pTarget->spr.cstat & CSTAT_SPRITE_BLOCK_ALL) == 0)
|
2021-10-15 20:55:03 +00:00
|
|
|
{
|
2021-10-26 18:13:03 +00:00
|
|
|
pEgg->pTarget = nullptr;
|
2021-10-15 20:55:03 +00:00
|
|
|
pEgg->nAction = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-10-26 18:13:03 +00:00
|
|
|
pTarget = FindPlayer(pActor, 1000, true);
|
|
|
|
pEgg->pTarget = pTarget;
|
2021-10-15 20:55:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (nAction)
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
{
|
2021-10-26 18:13:03 +00:00
|
|
|
auto nMov = MoveCreature(pActor);
|
2020-03-02 21:08:31 +00:00
|
|
|
|
2021-10-26 18:13:03 +00:00
|
|
|
if (nMov.exbits & kHitAux2)
|
2019-08-31 07:47:15 +00:00
|
|
|
{
|
2021-10-15 20:55:03 +00:00
|
|
|
if (!RandomSize(1))
|
|
|
|
{
|
|
|
|
pEgg->nAction = 1;
|
|
|
|
pEgg->nFrame = 0;
|
|
|
|
}
|
|
|
|
else
|
2019-08-31 07:47:15 +00:00
|
|
|
{
|
|
|
|
DestroyEgg(nEgg);
|
|
|
|
}
|
2021-10-15 20:55:03 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-11-16 17:41:34 +00:00
|
|
|
int nAngle;
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-10-26 18:13:03 +00:00
|
|
|
switch (nMov.type)
|
2021-10-15 20:55:03 +00:00
|
|
|
{
|
|
|
|
default:
|
|
|
|
return;
|
2021-10-26 18:13:03 +00:00
|
|
|
case kHitWall:
|
2021-11-26 13:26:03 +00:00
|
|
|
nAngle = GetWallNormal(nMov.hitWall);
|
2021-10-15 20:55:03 +00:00
|
|
|
break;
|
2021-10-26 18:13:03 +00:00
|
|
|
case kHitSprite:
|
2021-12-21 22:18:23 +00:00
|
|
|
nAngle = nMov.actor()->spr.ang;
|
2021-10-15 20:55:03 +00:00
|
|
|
break;
|
2019-08-31 07:47:15 +00:00
|
|
|
}
|
|
|
|
|
2021-12-23 16:05:44 +00:00
|
|
|
pActor->spr.ang = nAngle;
|
|
|
|
pActor->spr.xvel = bcos(nAngle, -1);
|
|
|
|
pActor->spr.yvel = bsin(nAngle, -1);
|
2021-10-15 20:55:03 +00:00
|
|
|
}
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-10-15 20:55:03 +00:00
|
|
|
break;
|
|
|
|
}
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-10-15 20:55:03 +00:00
|
|
|
case 1:
|
|
|
|
{
|
|
|
|
if (bVal)
|
|
|
|
{
|
|
|
|
pEgg->nAction = 3;
|
2021-12-23 16:05:44 +00:00
|
|
|
pActor->spr.cstat = CSTAT_SPRITE_BLOCK_ALL;
|
2021-10-15 20:55:03 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-10-15 20:55:03 +00:00
|
|
|
case 2:
|
|
|
|
case 3:
|
|
|
|
{
|
2021-10-26 18:52:25 +00:00
|
|
|
auto nMov = QueenAngleChase(pActor, pTarget, nHeadVel, 64);
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-10-26 18:52:25 +00:00
|
|
|
switch (nMov.type)
|
2021-10-15 20:55:03 +00:00
|
|
|
{
|
2021-10-26 18:52:25 +00:00
|
|
|
case kHitSprite:
|
2021-12-21 22:18:23 +00:00
|
|
|
if (nMov.actor()->spr.statnum != 121)
|
2019-08-31 07:47:15 +00:00
|
|
|
{
|
2021-11-26 13:26:03 +00:00
|
|
|
runlist_DamageEnemy(nMov.actor(), pActor, 5);
|
2021-10-15 20:55:03 +00:00
|
|
|
}
|
2021-10-26 18:52:25 +00:00
|
|
|
[[fallthrough]];
|
|
|
|
case kHitWall:
|
2021-12-23 16:05:44 +00:00
|
|
|
pActor->spr.ang += (RandomSize(9) + 768);
|
|
|
|
pActor->spr.ang &= kAngleMask;
|
|
|
|
pActor->spr.xvel = bcos(pActor->spr.ang, -3);
|
|
|
|
pActor->spr.yvel = bsin(pActor->spr.ang, -3);
|
|
|
|
pActor->spr.zvel = -RandomSize(5);
|
2021-10-15 20:55:03 +00:00
|
|
|
break;
|
|
|
|
}
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-10-15 20:55:03 +00:00
|
|
|
return;
|
|
|
|
}
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-10-15 20:55:03 +00:00
|
|
|
case 4:
|
|
|
|
{
|
2021-10-26 18:13:03 +00:00
|
|
|
auto nMov = MoveCreature(pActor);
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-10-26 18:13:03 +00:00
|
|
|
if (nMov.exbits & kHitAux2)
|
2021-10-15 20:55:03 +00:00
|
|
|
{
|
2021-12-23 16:05:44 +00:00
|
|
|
pActor->spr.zvel = -(pActor->spr.zvel - 256);
|
|
|
|
if (pActor->spr.zvel < -512)
|
2021-10-15 20:55:03 +00:00
|
|
|
{
|
2021-12-23 16:05:44 +00:00
|
|
|
pActor->spr.zvel = 0;
|
2021-10-15 20:55:03 +00:00
|
|
|
}
|
|
|
|
}
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-10-20 09:20:49 +00:00
|
|
|
pEgg->nCounter--;
|
|
|
|
if (pEgg->nCounter <= 0)
|
2021-10-15 20:55:03 +00:00
|
|
|
{
|
2022-01-31 22:33:44 +00:00
|
|
|
auto pWaspSprite = BuildWasp(nullptr, pActor->int_pos().X, pActor->int_pos().Y, pActor->int_pos().Z, pActor->sector(), pActor->spr.ang, true);
|
|
|
|
pActor->set_int_z(pWaspSprite->int_pos().Z);
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-10-15 20:55:03 +00:00
|
|
|
DestroyEgg(nEgg);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-10-15 20:55:03 +00:00
|
|
|
void AIQueenEgg::RadialDamage(RunListEvent* ev)
|
|
|
|
{
|
2021-11-21 18:24:46 +00:00
|
|
|
int nEgg = RunData[ev->nRun].nObjIndex;
|
2021-10-15 20:55:03 +00:00
|
|
|
Egg* pEgg = &QueenEgg[nEgg];
|
2021-12-07 17:53:02 +00:00
|
|
|
DExhumedActor* pActor = pEgg->pActor;
|
|
|
|
if (!pActor) return;
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-12-23 18:05:20 +00:00
|
|
|
if (ev->pRadialActor->spr.statnum != 121 && (pActor->spr.cstat & CSTAT_SPRITE_BLOCK_ALL) != 0)
|
2021-10-15 20:55:03 +00:00
|
|
|
{
|
2021-10-26 18:13:03 +00:00
|
|
|
int nDamage = runlist_CheckRadialDamage(pActor);
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-10-15 20:55:03 +00:00
|
|
|
pEgg->nHealth -= nDamage;
|
|
|
|
}
|
|
|
|
}
|
2019-11-17 18:48:56 +00:00
|
|
|
|
2021-10-15 20:55:03 +00:00
|
|
|
void AIQueenEgg::Damage(RunListEvent* ev)
|
|
|
|
{
|
2021-11-21 18:24:46 +00:00
|
|
|
int nEgg = RunData[ev->nRun].nObjIndex;
|
2021-10-15 20:55:03 +00:00
|
|
|
Egg* pEgg = &QueenEgg[nEgg];
|
2019-11-17 18:48:56 +00:00
|
|
|
|
2021-10-15 20:55:03 +00:00
|
|
|
if (ev->nDamage != 0 && pEgg->nHealth > 0)
|
|
|
|
{
|
|
|
|
pEgg->nHealth -= ev->nDamage;
|
2019-11-17 18:48:56 +00:00
|
|
|
|
2021-10-15 20:55:03 +00:00
|
|
|
if (pEgg->nHealth <= 0)
|
|
|
|
DestroyEgg(nEgg);
|
|
|
|
}
|
|
|
|
}
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-10-15 20:55:03 +00:00
|
|
|
void AIQueenEgg::Draw(RunListEvent* ev)
|
|
|
|
{
|
2021-11-21 18:24:46 +00:00
|
|
|
int nEgg = RunData[ev->nRun].nObjIndex;
|
2021-10-15 20:55:03 +00:00
|
|
|
Egg* pEgg = &QueenEgg[nEgg];
|
2021-10-17 14:22:25 +00:00
|
|
|
seq_PlotSequence(ev->nParam, SeqOffsets[kSeqQueenEgg] + EggSeq[pEgg->nAction].a, pEgg->nFrame, EggSeq[pEgg->nAction].b);
|
2021-10-15 20:55:03 +00:00
|
|
|
}
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-11-21 18:24:46 +00:00
|
|
|
void BuildQueenHead(int nQueen)
|
2019-08-26 03:59:14 +00:00
|
|
|
{
|
2021-12-07 17:53:02 +00:00
|
|
|
DExhumedActor* pActor = QueenList[nQueen].pActor;
|
|
|
|
if (!pActor) return;
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2022-01-31 22:33:44 +00:00
|
|
|
int x = pActor->int_pos().X;
|
|
|
|
int y = pActor->int_pos().Y;
|
2021-12-23 16:05:44 +00:00
|
|
|
int nAngle = pActor->spr.ang;
|
2021-12-30 15:51:56 +00:00
|
|
|
auto pSector = pActor->sector();
|
2021-11-22 23:55:46 +00:00
|
|
|
int z = pSector->floorz;
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-11-22 23:55:46 +00:00
|
|
|
auto pActor2 = insertActor(pSector, 121);
|
2021-12-23 18:05:20 +00:00
|
|
|
|
2022-01-31 19:03:22 +00:00
|
|
|
pActor2->set_int_pos({ x, y, z });
|
2021-12-23 18:05:20 +00:00
|
|
|
pActor2->spr.clipdist = 70;
|
|
|
|
pActor2->spr.xrepeat = 80;
|
|
|
|
pActor2->spr.yrepeat = 80;
|
|
|
|
pActor2->spr.cstat = 0;
|
|
|
|
pActor2->spr.picnum = 1;
|
|
|
|
pActor2->spr.shade = -12;
|
|
|
|
pActor2->spr.pal = 0;
|
|
|
|
pActor2->spr.xoffset = 0;
|
|
|
|
pActor2->spr.yoffset = 0;
|
|
|
|
pActor2->spr.ang = nAngle;
|
2019-08-31 07:47:15 +00:00
|
|
|
|
|
|
|
nVelShift = 2;
|
2021-10-26 17:55:20 +00:00
|
|
|
SetHeadVel(pActor2);
|
2019-11-20 16:21:32 +00:00
|
|
|
|
2021-12-23 18:05:20 +00:00
|
|
|
pActor2->spr.zvel = -8192;
|
|
|
|
pActor2->spr.lotag = runlist_HeadRun() + 1;
|
|
|
|
pActor2->spr.hitag = 0;
|
|
|
|
pActor2->spr.extra = -1;
|
2019-08-31 07:47:15 +00:00
|
|
|
|
|
|
|
GrabTimeSlot(3);
|
|
|
|
|
2019-10-22 22:46:29 +00:00
|
|
|
QueenHead.nHealth = 800;
|
2019-08-31 07:47:15 +00:00
|
|
|
QueenHead.nAction = 0;
|
2021-10-26 19:10:51 +00:00
|
|
|
QueenHead.pTarget = QueenList[nQueen].pTarget;
|
2020-11-29 23:40:25 +00:00
|
|
|
QueenHead.nFrame = 0;
|
2021-10-26 17:55:20 +00:00
|
|
|
QueenHead.pActor = pActor2;
|
2021-10-20 09:20:49 +00:00
|
|
|
QueenHead.nIndex = 0;
|
|
|
|
QueenHead.nChannel = QueenList[nQueen].nChannel;
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2022-05-23 22:30:41 +00:00
|
|
|
pActor2->spr.intowner = runlist_AddRunRec(pActor2->spr.lotag - 1, 0, 0x1B0000);
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-10-20 09:20:49 +00:00
|
|
|
QueenHead.nRun = runlist_AddRunRec(NewRun, 0, 0x1B0000);
|
|
|
|
QueenHead.nIndex2 = 0;
|
2019-08-26 03:59:14 +00:00
|
|
|
}
|
|
|
|
|
2021-10-15 20:55:03 +00:00
|
|
|
void AIQueenHead::Tick(RunListEvent* ev)
|
2019-08-26 03:59:14 +00:00
|
|
|
{
|
2021-12-07 17:53:02 +00:00
|
|
|
DExhumedActor* pActor = QueenHead.pActor;
|
|
|
|
if (!pActor) return;
|
2021-12-30 09:30:21 +00:00
|
|
|
|
2021-11-21 18:24:46 +00:00
|
|
|
int nAction = QueenHead.nAction;
|
|
|
|
int nHd;
|
2019-08-31 07:47:15 +00:00
|
|
|
int var_14 = 0;
|
|
|
|
|
2021-10-15 20:55:03 +00:00
|
|
|
if (nAction == 0) {
|
2021-10-26 17:55:20 +00:00
|
|
|
Gravity(pActor);
|
2021-10-15 20:55:03 +00:00
|
|
|
}
|
|
|
|
|
2021-11-21 18:24:46 +00:00
|
|
|
int nSeq = SeqOffsets[kSeqQueen] + HeadSeq[QueenHead.nAction].a;
|
2021-10-15 20:55:03 +00:00
|
|
|
|
2021-10-26 17:55:20 +00:00
|
|
|
seq_MoveSequence(pActor, nSeq, QueenHead.nFrame);
|
2021-10-15 20:55:03 +00:00
|
|
|
|
2021-12-23 16:05:44 +00:00
|
|
|
pActor->spr.picnum = seq_GetSeqPicnum2(nSeq, QueenHead.nFrame);
|
2021-10-15 20:55:03 +00:00
|
|
|
|
|
|
|
QueenHead.nFrame++;
|
|
|
|
if (QueenHead.nFrame >= SeqSize[nSeq])
|
2019-08-31 07:47:15 +00:00
|
|
|
{
|
2021-10-15 20:55:03 +00:00
|
|
|
QueenHead.nFrame = 0;
|
|
|
|
var_14 = 1;
|
|
|
|
}
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-12-07 17:53:02 +00:00
|
|
|
DExhumedActor* pTarget = QueenHead.pTarget;
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-10-26 18:13:03 +00:00
|
|
|
if (pTarget)
|
2021-10-15 20:55:03 +00:00
|
|
|
{
|
2021-12-21 22:18:23 +00:00
|
|
|
if (!(pTarget->spr.cstat & CSTAT_SPRITE_BLOCK_ALL))
|
2021-10-15 20:55:03 +00:00
|
|
|
{
|
2021-10-26 17:55:20 +00:00
|
|
|
pTarget = nullptr;
|
|
|
|
QueenHead.pTarget = pTarget;
|
2021-10-15 20:55:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-10-26 17:55:20 +00:00
|
|
|
pTarget = FindPlayer(pActor, 1000);
|
|
|
|
QueenHead.pTarget = pTarget;
|
2021-10-15 20:55:03 +00:00
|
|
|
}
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-10-15 20:55:03 +00:00
|
|
|
switch (nAction)
|
|
|
|
{
|
|
|
|
case 0:
|
2021-10-20 09:20:49 +00:00
|
|
|
if (QueenHead.nIndex > 0)
|
2021-10-15 20:55:03 +00:00
|
|
|
{
|
2021-10-20 09:20:49 +00:00
|
|
|
QueenHead.nIndex--;
|
|
|
|
if (QueenHead.nIndex == 0)
|
2021-10-15 20:55:03 +00:00
|
|
|
{
|
|
|
|
BuildTail();
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-10-15 20:55:03 +00:00
|
|
|
QueenHead.nAction = 6;
|
|
|
|
nHeadVel = 800;
|
2021-12-23 16:05:44 +00:00
|
|
|
pActor->spr.cstat = CSTAT_SPRITE_BLOCK_ALL;
|
2021-10-15 20:55:03 +00:00
|
|
|
}
|
2021-10-20 09:20:49 +00:00
|
|
|
else if (QueenHead.nIndex < 60)
|
2019-08-31 07:47:15 +00:00
|
|
|
{
|
2021-12-23 16:05:44 +00:00
|
|
|
pActor->spr.shade--;
|
2019-08-31 07:47:15 +00:00
|
|
|
}
|
2021-10-15 20:55:03 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-10-26 17:55:20 +00:00
|
|
|
auto nMov = MoveCreature(pActor);
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-10-15 20:55:03 +00:00
|
|
|
// original BUG - this line doesn't exist in original code?
|
2021-12-23 16:05:44 +00:00
|
|
|
int nNewAng = pActor->spr.ang;
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-10-26 17:55:20 +00:00
|
|
|
if (nMov.exbits == 0)
|
|
|
|
{
|
2021-12-21 22:18:23 +00:00
|
|
|
if (nMov.type == kHitSprite) nNewAng = nMov.actor()->spr.ang;
|
2021-11-26 13:26:03 +00:00
|
|
|
else if (nMov.type == kHitWall) nNewAng = GetWallNormal(nMov.hitWall);
|
2021-10-26 17:55:20 +00:00
|
|
|
}
|
|
|
|
else if (nMov.exbits == kHitAux2)
|
2019-08-31 07:47:15 +00:00
|
|
|
{
|
2021-12-23 16:05:44 +00:00
|
|
|
pActor->spr.zvel = -(pActor->spr.zvel >> 1);
|
2021-10-15 20:55:03 +00:00
|
|
|
|
2021-12-23 16:05:44 +00:00
|
|
|
if (pActor->spr.zvel > -256)
|
2019-08-31 07:47:15 +00:00
|
|
|
{
|
2021-10-15 20:55:03 +00:00
|
|
|
nVelShift = 100;
|
2021-12-23 16:05:44 +00:00
|
|
|
pActor->spr.zvel = 0;
|
2019-08-31 07:47:15 +00:00
|
|
|
}
|
|
|
|
}
|
2021-10-15 20:55:03 +00:00
|
|
|
|
|
|
|
// original BUG - var_18 isn't being set if the check above == 0x20000 ?
|
2021-12-23 16:05:44 +00:00
|
|
|
pActor->spr.ang = nNewAng;
|
2021-10-15 20:55:03 +00:00
|
|
|
nVelShift++;
|
|
|
|
|
|
|
|
if (nVelShift < 5)
|
2019-11-17 18:48:56 +00:00
|
|
|
{
|
2021-10-26 17:55:20 +00:00
|
|
|
SetHeadVel(pActor);
|
2019-11-17 18:48:56 +00:00
|
|
|
}
|
2021-10-15 20:55:03 +00:00
|
|
|
else
|
2019-08-31 07:47:15 +00:00
|
|
|
{
|
2021-12-23 16:05:44 +00:00
|
|
|
pActor->spr.xvel = 0;
|
|
|
|
pActor->spr.yvel = 0;
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-12-23 16:05:44 +00:00
|
|
|
if (pActor->spr.zvel == 0)
|
2021-10-15 20:55:03 +00:00
|
|
|
{
|
2021-10-20 09:20:49 +00:00
|
|
|
QueenHead.nIndex = 120;
|
2021-10-15 20:55:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-10-15 20:55:03 +00:00
|
|
|
break;
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-10-15 20:55:03 +00:00
|
|
|
case 6:
|
|
|
|
if (var_14)
|
|
|
|
{
|
|
|
|
QueenHead.nAction = 1;
|
|
|
|
QueenHead.nFrame = 0;
|
|
|
|
break;
|
|
|
|
}
|
2021-10-26 17:55:20 +00:00
|
|
|
[[fallthrough]];
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-10-15 20:55:03 +00:00
|
|
|
case 1:
|
2022-01-31 22:33:44 +00:00
|
|
|
if ((pTarget->int_pos().Z - 51200) > pActor->int_pos().Z)
|
2021-10-15 20:55:03 +00:00
|
|
|
{
|
|
|
|
QueenHead.nAction = 4;
|
|
|
|
QueenHead.nFrame = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2022-01-31 19:03:22 +00:00
|
|
|
pActor->add_int_z(-2048);
|
2021-10-15 20:55:03 +00:00
|
|
|
goto __MOVEQS;
|
|
|
|
}
|
|
|
|
break;
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-10-15 20:55:03 +00:00
|
|
|
case 4:
|
|
|
|
case 7:
|
|
|
|
case 8:
|
|
|
|
if (var_14)
|
|
|
|
{
|
|
|
|
int nRnd = RandomSize(2);
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-10-15 20:55:03 +00:00
|
|
|
if (nRnd == 0)
|
|
|
|
{
|
|
|
|
QueenHead.nAction = 4;
|
|
|
|
}
|
|
|
|
else if (nRnd == 1)
|
|
|
|
{
|
|
|
|
QueenHead.nAction = 7;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
QueenHead.nAction = 8;
|
|
|
|
}
|
|
|
|
}
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-10-26 17:55:20 +00:00
|
|
|
if (pTarget)
|
2021-10-15 20:55:03 +00:00
|
|
|
{
|
2021-10-26 18:52:25 +00:00
|
|
|
auto nMov = QueenAngleChase(pActor, pTarget, nHeadVel, 64);
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-10-26 18:52:25 +00:00
|
|
|
if (nMov.type == kHitSprite)
|
2021-10-15 20:55:03 +00:00
|
|
|
{
|
2021-11-26 13:26:03 +00:00
|
|
|
if (nMov.actor() == pTarget)
|
2021-10-15 20:55:03 +00:00
|
|
|
{
|
2021-10-26 17:55:20 +00:00
|
|
|
runlist_DamageEnemy(pTarget, pActor, 10);
|
|
|
|
D3PlayFX(StaticSound[kSoundQTail] | 0x2000, pActor);
|
2019-11-17 18:48:56 +00:00
|
|
|
|
2021-12-23 16:05:44 +00:00
|
|
|
pActor->spr.ang += RandomSize(9) + 768;
|
|
|
|
pActor->spr.ang &= kAngleMask;
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-12-23 16:05:44 +00:00
|
|
|
pActor->spr.zvel = (-20) - RandomSize(6);
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-10-26 17:55:20 +00:00
|
|
|
SetHeadVel(pActor);
|
2021-10-15 20:55:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-10-15 20:55:03 +00:00
|
|
|
// switch break. MoveQS stuff?
|
|
|
|
__MOVEQS:
|
2022-01-31 22:33:44 +00:00
|
|
|
MoveQX[nQHead] = pActor->int_pos().X;
|
|
|
|
MoveQY[nQHead] = pActor->int_pos().Y;
|
|
|
|
MoveQZ[nQHead] = pActor->int_pos().Z;
|
2021-12-30 15:51:56 +00:00
|
|
|
assert(pActor->sector());
|
|
|
|
MoveQS[nQHead] = pActor->sector();
|
2021-12-23 16:05:44 +00:00
|
|
|
MoveQA[nQHead] = pActor->spr.ang;
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-10-15 20:55:03 +00:00
|
|
|
nHd = nQHead;
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-10-20 09:20:49 +00:00
|
|
|
for (int i = 0; i < QueenHead.nIndex2; i++)
|
2021-10-15 20:55:03 +00:00
|
|
|
{
|
|
|
|
nHd -= 3;
|
|
|
|
if (nHd < 0) {
|
|
|
|
nHd += (24 + 1); // TODO - enum/define for these
|
|
|
|
//assert(nHd < 24 && nHd >= 0);
|
|
|
|
}
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-11-23 00:15:28 +00:00
|
|
|
auto headSect = MoveQS[nHd];
|
2021-12-07 17:53:02 +00:00
|
|
|
DExhumedActor* pTActor = tailspr[i];
|
2021-10-26 19:10:51 +00:00
|
|
|
if (pTActor)
|
2021-10-15 20:55:03 +00:00
|
|
|
{
|
2021-12-30 15:51:56 +00:00
|
|
|
if (headSect != pTActor->sector())
|
2021-10-26 19:10:51 +00:00
|
|
|
{
|
2021-11-23 00:15:28 +00:00
|
|
|
assert(headSect);
|
|
|
|
ChangeActorSect(pTActor, headSect);
|
2021-10-26 19:10:51 +00:00
|
|
|
}
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2022-01-31 19:03:22 +00:00
|
|
|
pTActor->set_int_pos({ MoveQX[nHd], MoveQY[nHd], MoveQZ[nHd] });
|
2021-12-23 18:05:20 +00:00
|
|
|
pTActor->spr.ang = MoveQA[nHd];
|
2021-10-26 19:10:51 +00:00
|
|
|
}
|
2021-10-15 20:55:03 +00:00
|
|
|
}
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-10-15 20:55:03 +00:00
|
|
|
nQHead++;
|
|
|
|
if (nQHead >= 25)
|
|
|
|
{
|
|
|
|
nQHead = 0;
|
|
|
|
}
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-10-15 20:55:03 +00:00
|
|
|
break;
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-10-15 20:55:03 +00:00
|
|
|
case 5:
|
2021-10-20 09:20:49 +00:00
|
|
|
QueenHead.nIndex--;
|
|
|
|
if (QueenHead.nIndex <= 0)
|
2021-10-15 20:55:03 +00:00
|
|
|
{
|
2021-10-20 09:20:49 +00:00
|
|
|
QueenHead.nIndex = 3;
|
2019-11-17 18:48:56 +00:00
|
|
|
|
2021-10-20 09:20:49 +00:00
|
|
|
if (QueenHead.nIndex2--)
|
2021-10-15 20:55:03 +00:00
|
|
|
{
|
2021-10-20 09:20:49 +00:00
|
|
|
if (QueenHead.nIndex2 >= 15 || QueenHead.nIndex2 < 10)
|
2021-10-15 20:55:03 +00:00
|
|
|
{
|
2022-01-31 22:33:44 +00:00
|
|
|
int x = pActor->int_pos().X;
|
|
|
|
int y = pActor->int_pos().Y;
|
|
|
|
int z = pActor->int_pos().Z;
|
2021-12-30 15:51:56 +00:00
|
|
|
auto pSector =pActor->sector();
|
2021-10-15 20:55:03 +00:00
|
|
|
int nAngle = RandomSize(11) & kAngleMask;
|
2019-11-17 18:48:56 +00:00
|
|
|
|
2021-12-23 16:05:44 +00:00
|
|
|
pActor->spr.xrepeat = 127 - QueenHead.nIndex2;
|
|
|
|
pActor->spr.yrepeat = 127 - QueenHead.nIndex2;
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-12-23 16:05:44 +00:00
|
|
|
pActor->spr.cstat = CSTAT_SPRITE_INVISIBLE;
|
2021-10-15 20:55:03 +00:00
|
|
|
|
|
|
|
// DEMO-TODO: in disassembly angle was used without masking and thus causing OOB issue.
|
|
|
|
// This behavior probably would be needed emulated for demo compatibility
|
|
|
|
int dx = bcos(nAngle, 10);
|
|
|
|
int dy = bsin(nAngle, 10);
|
|
|
|
int dz = (RandomSize(5) - RandomSize(5)) << 7;
|
2019-11-17 18:48:56 +00:00
|
|
|
|
2021-10-26 17:55:20 +00:00
|
|
|
movesprite(pActor, dx, dy, dz, 0, 0, CLIPMASK1);
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-10-26 19:10:51 +00:00
|
|
|
BlowChunks(pActor);
|
2021-10-26 17:55:20 +00:00
|
|
|
BuildExplosion(pActor);
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-11-23 00:15:28 +00:00
|
|
|
ChangeActorSect(pActor, pSector);
|
2019-11-17 18:48:56 +00:00
|
|
|
|
2022-01-31 19:03:22 +00:00
|
|
|
pActor->set_int_pos({ x, y, z });
|
2021-10-15 20:55:03 +00:00
|
|
|
|
2021-10-20 09:20:49 +00:00
|
|
|
if (QueenHead.nIndex2 < 10) {
|
|
|
|
for (int i = (10 - QueenHead.nIndex2) * 2; i > 0; i--)
|
2021-10-15 20:55:03 +00:00
|
|
|
{
|
2021-10-26 17:55:20 +00:00
|
|
|
BuildLavaLimb(pActor, i, GetActorHeight(pActor));
|
2019-08-31 07:47:15 +00:00
|
|
|
}
|
|
|
|
}
|
2021-10-15 20:55:03 +00:00
|
|
|
}
|
2019-11-17 18:48:56 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-10-26 17:55:20 +00:00
|
|
|
BuildExplosion(pActor);
|
2019-11-17 18:48:56 +00:00
|
|
|
|
2021-10-15 20:55:03 +00:00
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < 10; i++)
|
2019-11-17 18:48:56 +00:00
|
|
|
{
|
2021-10-26 19:10:51 +00:00
|
|
|
BlowChunks(pActor);
|
2019-08-31 07:47:15 +00:00
|
|
|
}
|
|
|
|
|
2021-10-15 20:55:03 +00:00
|
|
|
for (i = 0; i < 20; i++)
|
2019-08-31 07:47:15 +00:00
|
|
|
{
|
2021-10-26 17:55:20 +00:00
|
|
|
BuildLavaLimb(pActor, i, GetActorHeight(pActor));
|
2019-08-31 07:47:15 +00:00
|
|
|
}
|
2021-10-15 20:55:03 +00:00
|
|
|
|
2022-05-23 22:30:41 +00:00
|
|
|
runlist_SubRunRec(pActor->spr.intowner);
|
2021-10-20 09:20:49 +00:00
|
|
|
runlist_SubRunRec(QueenHead.nRun);
|
2021-10-26 17:55:20 +00:00
|
|
|
DeleteActor(pActor);
|
2021-10-20 09:20:49 +00:00
|
|
|
runlist_ChangeChannel(QueenHead.nChannel, 1);
|
2019-08-31 07:47:15 +00:00
|
|
|
}
|
2021-10-15 20:55:03 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-10-15 20:55:03 +00:00
|
|
|
void AIQueenHead::RadialDamage(RunListEvent* ev)
|
|
|
|
{
|
2021-12-23 18:05:20 +00:00
|
|
|
if (ev->pRadialActor->spr.statnum != 121 && (QueenHead.pActor->spr.cstat & CSTAT_SPRITE_BLOCK_ALL) != 0)
|
2021-10-15 20:55:03 +00:00
|
|
|
{
|
2021-10-26 17:55:20 +00:00
|
|
|
ev->nDamage = runlist_CheckRadialDamage(QueenHead.pActor);
|
2021-10-15 20:55:03 +00:00
|
|
|
if (ev->nDamage) Damage(ev);
|
|
|
|
}
|
|
|
|
}
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-10-15 20:55:03 +00:00
|
|
|
void AIQueenHead::Damage(RunListEvent* ev)
|
|
|
|
{
|
2021-12-07 17:53:02 +00:00
|
|
|
DExhumedActor* pActor = QueenHead.pActor;
|
|
|
|
if (!pActor) return;
|
2021-10-15 20:55:03 +00:00
|
|
|
|
|
|
|
if (QueenHead.nHealth > 0 && ev->nDamage != 0)
|
|
|
|
{
|
|
|
|
QueenHead.nHealth -= ev->nDamage;
|
|
|
|
|
|
|
|
if (!RandomSize(4))
|
|
|
|
{
|
2021-10-26 17:55:20 +00:00
|
|
|
QueenHead.pTarget = ev->pOtherActor;
|
2021-10-15 20:55:03 +00:00
|
|
|
QueenHead.nAction = 7;
|
|
|
|
QueenHead.nFrame = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (QueenHead.nHealth <= 0)
|
|
|
|
{
|
|
|
|
if (DestroyTailPart())
|
2019-08-31 07:47:15 +00:00
|
|
|
{
|
2021-10-15 20:55:03 +00:00
|
|
|
QueenHead.nHealth = 200;
|
|
|
|
nHeadVel += 100;
|
2019-08-31 07:47:15 +00:00
|
|
|
}
|
2019-11-17 18:48:56 +00:00
|
|
|
else
|
2019-08-31 07:47:15 +00:00
|
|
|
{
|
2021-10-15 20:55:03 +00:00
|
|
|
QueenHead.nAction = 5;
|
|
|
|
QueenHead.nFrame = 0;
|
2021-10-20 09:20:49 +00:00
|
|
|
QueenHead.nIndex = 0;
|
|
|
|
QueenHead.nIndex2 = 80;
|
2021-12-23 16:05:44 +00:00
|
|
|
pActor->spr.cstat = 0;
|
2019-08-31 07:47:15 +00:00
|
|
|
}
|
2019-11-17 18:48:56 +00:00
|
|
|
}
|
2021-10-15 20:55:03 +00:00
|
|
|
}
|
|
|
|
}
|
2019-11-17 18:48:56 +00:00
|
|
|
|
2021-10-15 20:55:03 +00:00
|
|
|
void AIQueenHead::Draw(RunListEvent* ev)
|
|
|
|
{
|
2021-11-21 18:24:46 +00:00
|
|
|
int nHead = RunData[ev->nRun].nObjIndex;
|
|
|
|
int nAction = QueenHead.nAction;
|
2021-10-15 20:55:03 +00:00
|
|
|
|
2021-11-21 18:24:46 +00:00
|
|
|
int nSeq = SeqOffsets[kSeqQueen];
|
2021-10-15 20:55:03 +00:00
|
|
|
|
|
|
|
int edx;
|
|
|
|
|
|
|
|
if (nHead == 0)
|
|
|
|
{
|
|
|
|
edx = HeadSeq[nAction].b;
|
|
|
|
nSeq += HeadSeq[nAction].a;
|
2019-08-31 07:47:15 +00:00
|
|
|
}
|
2021-10-15 20:55:03 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
edx = 1;
|
|
|
|
nSeq += 73;
|
|
|
|
}
|
|
|
|
|
2021-10-17 14:22:25 +00:00
|
|
|
seq_PlotSequence(ev->nParam, nSeq, QueenHead.nFrame, edx);
|
2021-10-15 20:55:03 +00:00
|
|
|
}
|
|
|
|
|
2021-11-23 00:18:20 +00:00
|
|
|
void BuildQueen(DExhumedActor* pActor, int x, int y, int z, sectortype* pSector, int nAngle, int nChannel)
|
2019-08-26 03:59:14 +00:00
|
|
|
{
|
2019-08-31 07:47:15 +00:00
|
|
|
QueenCount--;
|
|
|
|
|
2021-11-21 18:24:46 +00:00
|
|
|
int nQueen = QueenCount;
|
2019-08-31 07:47:15 +00:00
|
|
|
if (nQueen < 0) {
|
2021-10-15 16:37:39 +00:00
|
|
|
return;
|
2019-08-31 07:47:15 +00:00
|
|
|
}
|
|
|
|
|
2021-10-26 19:10:51 +00:00
|
|
|
if (pActor == nullptr)
|
2019-08-31 07:47:15 +00:00
|
|
|
{
|
2021-11-23 00:18:20 +00:00
|
|
|
pActor = insertActor(pSector, 121);
|
2019-08-31 07:47:15 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-10-26 19:10:51 +00:00
|
|
|
ChangeActorStat(pActor, 121);
|
2022-01-31 22:33:44 +00:00
|
|
|
x = pActor->int_pos().X;
|
|
|
|
y = pActor->int_pos().Y;
|
2021-12-30 15:51:56 +00:00
|
|
|
z = pActor->sector()->floorz;
|
2021-12-23 16:05:44 +00:00
|
|
|
nAngle = pActor->spr.ang;
|
2019-08-31 07:47:15 +00:00
|
|
|
}
|
|
|
|
|
2022-01-31 19:03:22 +00:00
|
|
|
pActor->set_int_pos({ x, y, z });
|
2021-12-23 16:05:44 +00:00
|
|
|
pActor->spr.cstat = CSTAT_SPRITE_BLOCK_ALL;
|
|
|
|
pActor->spr.pal = 0;
|
|
|
|
pActor->spr.shade = -12;
|
|
|
|
pActor->spr.clipdist = 100;
|
|
|
|
pActor->spr.xrepeat = 80;
|
|
|
|
pActor->spr.yrepeat = 80;
|
|
|
|
pActor->spr.xoffset = 0;
|
|
|
|
pActor->spr.yoffset = 0;
|
|
|
|
pActor->spr.picnum = 1;
|
|
|
|
pActor->spr.ang = nAngle;
|
|
|
|
pActor->spr.xvel = 0;
|
|
|
|
pActor->spr.yvel = 0;
|
|
|
|
pActor->spr.zvel = 0;
|
|
|
|
pActor->spr.lotag = runlist_HeadRun() + 1;
|
|
|
|
pActor->spr.extra = -1;
|
|
|
|
pActor->spr.hitag = 0;
|
2019-08-31 07:47:15 +00:00
|
|
|
|
|
|
|
GrabTimeSlot(3);
|
|
|
|
|
|
|
|
QueenList[nQueen].nAction = 0;
|
2019-10-22 22:46:29 +00:00
|
|
|
QueenList[nQueen].nHealth = 4000;
|
2020-03-02 21:08:31 +00:00
|
|
|
QueenList[nQueen].nFrame = 0;
|
2021-10-26 19:10:51 +00:00
|
|
|
QueenList[nQueen].pActor = pActor;
|
|
|
|
QueenList[nQueen].pTarget = nullptr;
|
2021-10-20 09:20:49 +00:00
|
|
|
QueenList[nQueen].nAction2 = 0;
|
|
|
|
QueenList[nQueen].nIndex2 = 5;
|
|
|
|
QueenList[nQueen].nIndex = 0;
|
|
|
|
QueenList[nQueen].nChannel = nChannel;
|
2019-08-31 07:47:15 +00:00
|
|
|
|
|
|
|
nHeadVel = 800;
|
|
|
|
|
2022-05-23 22:30:41 +00:00
|
|
|
pActor->spr.intowner = runlist_AddRunRec(pActor->spr.lotag - 1, nQueen, 0x1A0000);
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-10-15 16:37:39 +00:00
|
|
|
runlist_AddRunRec(NewRun, nQueen, 0x1A0000);
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2020-08-23 12:39:14 +00:00
|
|
|
nCreaturesTotal++;
|
2019-08-26 03:59:14 +00:00
|
|
|
}
|
|
|
|
|
2021-10-26 19:10:51 +00:00
|
|
|
void SetQueenSpeed(DExhumedActor* pActor, int nSpeed)
|
2019-08-26 03:59:14 +00:00
|
|
|
{
|
2021-12-23 16:05:44 +00:00
|
|
|
pActor->spr.xvel = bcos(pActor->spr.ang, -(2 - nSpeed));
|
|
|
|
pActor->spr.yvel = bsin(pActor->spr.ang, -(2 - nSpeed));
|
2019-08-26 03:59:14 +00:00
|
|
|
}
|
|
|
|
|
2021-10-15 20:55:03 +00:00
|
|
|
void AIQueen::Tick(RunListEvent* ev)
|
2019-08-26 03:59:14 +00:00
|
|
|
{
|
2021-11-21 18:24:46 +00:00
|
|
|
int nQueen = RunData[ev->nRun].nObjIndex;
|
2019-08-31 07:47:15 +00:00
|
|
|
assert(nQueen >= 0 && nQueen < kMaxQueens);
|
|
|
|
|
2021-12-07 17:53:02 +00:00
|
|
|
DExhumedActor* pActor = QueenList[nQueen].pActor;
|
|
|
|
if (!pActor) return;
|
2021-11-21 18:24:46 +00:00
|
|
|
int nAction = QueenList[nQueen].nAction;
|
|
|
|
int si = QueenList[nQueen].nAction2;
|
2021-12-07 17:53:02 +00:00
|
|
|
DExhumedActor* pTarget = QueenList[nQueen].pTarget;
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2020-03-02 21:08:31 +00:00
|
|
|
bool bVal = false;
|
|
|
|
|
2021-10-15 20:55:03 +00:00
|
|
|
if (si < 3) {
|
2021-10-26 19:10:51 +00:00
|
|
|
Gravity(pActor);
|
2021-10-15 20:55:03 +00:00
|
|
|
}
|
|
|
|
|
2021-11-21 18:24:46 +00:00
|
|
|
int nSeq = SeqOffsets[kSeqQueen] + QueenSeq[nAction].a;
|
2021-10-15 20:55:03 +00:00
|
|
|
|
2021-12-23 16:05:44 +00:00
|
|
|
pActor->spr.picnum = seq_GetSeqPicnum2(nSeq, QueenList[nQueen].nFrame);
|
2021-10-15 20:55:03 +00:00
|
|
|
|
2021-10-26 19:10:51 +00:00
|
|
|
seq_MoveSequence(pActor, nSeq, QueenList[nQueen].nFrame);
|
2021-10-15 20:55:03 +00:00
|
|
|
|
|
|
|
QueenList[nQueen].nFrame++;
|
|
|
|
if (QueenList[nQueen].nFrame >= SeqSize[nSeq])
|
2019-08-31 07:47:15 +00:00
|
|
|
{
|
2021-10-15 20:55:03 +00:00
|
|
|
QueenList[nQueen].nFrame = 0;
|
|
|
|
bVal = true;
|
|
|
|
}
|
2020-03-02 21:08:31 +00:00
|
|
|
|
2021-11-21 18:24:46 +00:00
|
|
|
int nFlag = FrameFlag[SeqBase[nSeq] + QueenList[nQueen].nFrame];
|
2020-03-02 21:08:31 +00:00
|
|
|
|
2021-10-26 19:10:51 +00:00
|
|
|
if (pActor != nullptr)
|
2021-10-15 20:55:03 +00:00
|
|
|
{
|
|
|
|
if (nAction < 7)
|
2019-08-31 07:47:15 +00:00
|
|
|
{
|
2021-12-23 16:05:44 +00:00
|
|
|
if (!(pActor->spr.cstat & CSTAT_SPRITE_BLOCK_ALL))
|
2021-10-15 20:55:03 +00:00
|
|
|
{
|
2021-10-26 19:10:51 +00:00
|
|
|
pTarget = nullptr;
|
|
|
|
QueenList[nQueen].pTarget = nullptr;
|
2021-10-15 20:55:03 +00:00
|
|
|
QueenList[nQueen].nAction = 0;
|
2019-08-31 07:47:15 +00:00
|
|
|
}
|
2021-10-15 20:55:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
switch (nAction)
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
{
|
2021-10-26 19:10:51 +00:00
|
|
|
if (pTarget == nullptr)
|
2021-10-15 20:55:03 +00:00
|
|
|
{
|
2021-10-26 19:10:51 +00:00
|
|
|
pTarget = FindPlayer(pActor, 60);
|
2021-10-15 20:55:03 +00:00
|
|
|
}
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-10-26 19:10:51 +00:00
|
|
|
if (pTarget)
|
2021-10-15 20:55:03 +00:00
|
|
|
{
|
2021-10-20 09:20:49 +00:00
|
|
|
QueenList[nQueen].nAction = QueenList[nQueen].nAction2 + 1;
|
2021-10-15 20:55:03 +00:00
|
|
|
QueenList[nQueen].nFrame = 0;
|
2021-10-26 19:10:51 +00:00
|
|
|
QueenList[nQueen].pTarget = pTarget;
|
2021-10-20 09:20:49 +00:00
|
|
|
QueenList[nQueen].nIndex = RandomSize(7);
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-10-26 19:10:51 +00:00
|
|
|
SetQueenSpeed(pActor, si);
|
2021-10-15 20:55:03 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-10-15 20:55:03 +00:00
|
|
|
case 6:
|
|
|
|
{
|
|
|
|
if (bVal)
|
|
|
|
{
|
|
|
|
BuildQueenEgg(nQueen, 1);
|
|
|
|
QueenList[nQueen].nAction = 3;
|
2021-10-20 09:20:49 +00:00
|
|
|
QueenList[nQueen].nIndex = RandomSize(6) + 60;
|
2021-10-15 20:55:03 +00:00
|
|
|
}
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-10-15 20:55:03 +00:00
|
|
|
break;
|
|
|
|
}
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-10-15 20:55:03 +00:00
|
|
|
case 1:
|
|
|
|
case 2:
|
|
|
|
case 3:
|
|
|
|
{
|
2021-10-20 09:20:49 +00:00
|
|
|
QueenList[nQueen].nIndex--;
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-10-15 20:55:03 +00:00
|
|
|
if ((nQueen & 0x1F) == (totalmoves & 0x1F))
|
|
|
|
{
|
|
|
|
if (si < 2)
|
2019-08-31 07:47:15 +00:00
|
|
|
{
|
2021-10-20 09:20:49 +00:00
|
|
|
if (QueenList[nQueen].nIndex <= 0)
|
2019-08-31 07:47:15 +00:00
|
|
|
{
|
2021-10-15 20:55:03 +00:00
|
|
|
QueenList[nQueen].nFrame = 0;
|
2021-12-23 16:05:44 +00:00
|
|
|
pActor->spr.xvel = 0;
|
|
|
|
pActor->spr.yvel = 0;
|
2021-10-15 20:55:03 +00:00
|
|
|
QueenList[nQueen].nAction = si + 4;
|
2021-10-20 09:20:49 +00:00
|
|
|
QueenList[nQueen].nIndex = RandomSize(6) + 30;
|
2021-10-15 20:55:03 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-10-20 09:20:49 +00:00
|
|
|
if (QueenList[nQueen].nIndex2 < 5)
|
2019-08-31 07:47:15 +00:00
|
|
|
{
|
2021-10-20 09:20:49 +00:00
|
|
|
QueenList[nQueen].nIndex2++;
|
2019-08-31 07:47:15 +00:00
|
|
|
}
|
2021-10-15 20:55:03 +00:00
|
|
|
|
|
|
|
// then to PLOTSPRITE
|
2019-08-31 07:47:15 +00:00
|
|
|
}
|
|
|
|
}
|
2021-10-15 20:55:03 +00:00
|
|
|
else
|
2019-08-31 07:47:15 +00:00
|
|
|
{
|
2021-10-20 09:20:49 +00:00
|
|
|
if (QueenList[nQueen].nIndex <= 0)
|
2019-08-31 07:47:15 +00:00
|
|
|
{
|
2021-10-24 11:20:50 +00:00
|
|
|
if (Counters[kCountWasp] < 100)
|
2019-08-31 07:47:15 +00:00
|
|
|
{
|
2021-10-15 20:55:03 +00:00
|
|
|
QueenList[nQueen].nAction = 6;
|
|
|
|
QueenList[nQueen].nFrame = 0;
|
|
|
|
break;
|
2019-08-31 07:47:15 +00:00
|
|
|
}
|
2021-10-15 20:55:03 +00:00
|
|
|
else
|
2019-11-17 18:48:56 +00:00
|
|
|
{
|
2021-10-20 09:20:49 +00:00
|
|
|
QueenList[nQueen].nIndex = 30000;
|
2021-10-15 20:55:03 +00:00
|
|
|
// then to PLOTSPRITE
|
2019-11-17 18:48:56 +00:00
|
|
|
}
|
|
|
|
}
|
2021-10-15 20:55:03 +00:00
|
|
|
}
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-10-15 20:55:03 +00:00
|
|
|
// loc_35B4B
|
2021-10-26 19:10:51 +00:00
|
|
|
PlotCourseToSprite(pActor, pTarget);
|
|
|
|
SetQueenSpeed(pActor, si);
|
2021-10-15 20:55:03 +00:00
|
|
|
}
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-10-26 19:10:51 +00:00
|
|
|
auto nMov = MoveCreatureWithCaution(pActor);
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-10-26 19:10:51 +00:00
|
|
|
switch (nMov.type)
|
2021-10-15 20:55:03 +00:00
|
|
|
{
|
2021-10-26 19:10:51 +00:00
|
|
|
case kHitSprite:
|
2021-11-26 13:26:03 +00:00
|
|
|
if ((si == 2) && (nMov.actor() == pTarget))
|
2021-10-15 20:55:03 +00:00
|
|
|
{
|
2021-10-26 19:10:51 +00:00
|
|
|
runlist_DamageEnemy(pTarget, pActor, 5);
|
2021-10-15 20:55:03 +00:00
|
|
|
break;
|
|
|
|
}
|
2021-10-26 18:52:25 +00:00
|
|
|
[[fallthrough]];
|
2021-10-15 20:55:03 +00:00
|
|
|
case 0x8000:
|
2021-12-23 16:05:44 +00:00
|
|
|
pActor->spr.ang += 256;
|
|
|
|
pActor->spr.ang &= kAngleMask;
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-10-26 19:10:51 +00:00
|
|
|
SetQueenSpeed(pActor, si);
|
2021-10-15 20:55:03 +00:00
|
|
|
break;
|
|
|
|
}
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-10-15 20:55:03 +00:00
|
|
|
// loc_35BD2
|
2021-10-26 19:10:51 +00:00
|
|
|
if (nAction && pTarget != nullptr)
|
2021-10-15 20:55:03 +00:00
|
|
|
{
|
2021-12-21 22:18:23 +00:00
|
|
|
if (!(pTarget->spr.cstat & CSTAT_SPRITE_BLOCK_ALL))
|
2021-10-15 20:55:03 +00:00
|
|
|
{
|
|
|
|
QueenList[nQueen].nAction = 0;
|
|
|
|
QueenList[nQueen].nFrame = 0;
|
2021-10-20 09:20:49 +00:00
|
|
|
QueenList[nQueen].nIndex = 100;
|
2021-10-26 19:10:51 +00:00
|
|
|
QueenList[nQueen].pTarget = nullptr;
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-12-23 16:05:44 +00:00
|
|
|
pActor->spr.xvel = 0;
|
|
|
|
pActor->spr.yvel = 0;
|
2021-10-15 20:55:03 +00:00
|
|
|
}
|
|
|
|
}
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-10-15 20:55:03 +00:00
|
|
|
break;
|
|
|
|
}
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-10-15 20:55:03 +00:00
|
|
|
case 4:
|
|
|
|
case 5:
|
|
|
|
{
|
2021-10-20 09:20:49 +00:00
|
|
|
if (bVal && QueenList[nQueen].nIndex2 <= 0)
|
2021-10-15 20:55:03 +00:00
|
|
|
{
|
|
|
|
QueenList[nQueen].nAction = 0;
|
2021-10-20 09:20:49 +00:00
|
|
|
QueenList[nQueen].nIndex = 15;
|
2021-10-15 20:55:03 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (nFlag & 0x80)
|
|
|
|
{
|
2021-10-20 09:20:49 +00:00
|
|
|
QueenList[nQueen].nIndex2--;
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-10-26 19:10:51 +00:00
|
|
|
PlotCourseToSprite(pActor, pTarget);
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-10-15 20:55:03 +00:00
|
|
|
if (!si)
|
2019-08-31 07:47:15 +00:00
|
|
|
{
|
2021-12-23 16:05:44 +00:00
|
|
|
BuildBullet(pActor, 12, -1, pActor->spr.ang, pTarget, 1);
|
2019-08-31 07:47:15 +00:00
|
|
|
}
|
2021-10-15 20:55:03 +00:00
|
|
|
else
|
2019-08-31 07:47:15 +00:00
|
|
|
{
|
2021-10-15 20:55:03 +00:00
|
|
|
BuildQueenEgg(nQueen, 0);
|
2019-08-31 07:47:15 +00:00
|
|
|
}
|
2021-10-15 20:55:03 +00:00
|
|
|
}
|
|
|
|
}
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-10-15 20:55:03 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case 7:
|
|
|
|
{
|
|
|
|
if (bVal)
|
|
|
|
{
|
|
|
|
QueenList[nQueen].nAction = 0;
|
|
|
|
QueenList[nQueen].nFrame = 0;
|
|
|
|
}
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-10-15 20:55:03 +00:00
|
|
|
break;
|
|
|
|
}
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-10-15 20:55:03 +00:00
|
|
|
case 8:
|
|
|
|
case 9:
|
|
|
|
{
|
|
|
|
if (bVal)
|
|
|
|
{
|
|
|
|
if (nAction == 9)
|
|
|
|
{
|
2021-10-20 09:20:49 +00:00
|
|
|
QueenList[nQueen].nIndex--;
|
|
|
|
if (QueenList[nQueen].nIndex <= 0)
|
2021-10-15 20:55:03 +00:00
|
|
|
{
|
2021-12-23 16:05:44 +00:00
|
|
|
pActor->spr.cstat = 0;
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-10-15 20:55:03 +00:00
|
|
|
for (int i = 0; i < 20; i++)
|
|
|
|
{
|
2021-10-26 19:15:07 +00:00
|
|
|
auto pChunkActor = BuildCreatureChunk(pActor, seq_GetSeqPicnum(kSeqQueen, 57, 0));
|
2019-11-17 18:48:56 +00:00
|
|
|
|
2021-12-21 22:18:23 +00:00
|
|
|
pChunkActor->spr.picnum = kQueenChunk + (i % 3);
|
|
|
|
pChunkActor->spr.xrepeat = 100;
|
|
|
|
pChunkActor->spr.yrepeat = 100;
|
2021-10-15 20:55:03 +00:00
|
|
|
}
|
2020-03-02 21:08:31 +00:00
|
|
|
|
2021-10-26 19:15:07 +00:00
|
|
|
auto pChunkActor = BuildCreatureChunk(pActor, seq_GetSeqPicnum(kSeqQueen, 57, 0));
|
2020-03-02 21:08:31 +00:00
|
|
|
|
2021-12-21 22:18:23 +00:00
|
|
|
pChunkActor->spr.picnum = kTile3126;
|
|
|
|
pChunkActor->spr.yrepeat = 100;
|
|
|
|
pChunkActor->spr.xrepeat = 100;
|
2019-11-17 18:48:56 +00:00
|
|
|
|
2021-10-15 20:55:03 +00:00
|
|
|
PlayFXAtXYZ(
|
|
|
|
StaticSound[kSound40],
|
2022-01-31 22:33:44 +00:00
|
|
|
pActor->int_pos().X,
|
|
|
|
pActor->int_pos().Y,
|
|
|
|
pActor->int_pos().Z);
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-10-15 20:55:03 +00:00
|
|
|
BuildQueenHead(nQueen);
|
2019-08-31 07:47:15 +00:00
|
|
|
|
2021-10-15 20:55:03 +00:00
|
|
|
QueenList[nQueen].nAction++;
|
2019-11-17 18:48:56 +00:00
|
|
|
}
|
|
|
|
}
|
2021-10-15 20:55:03 +00:00
|
|
|
else
|
|
|
|
QueenList[nQueen].nAction++;
|
2019-11-17 18:48:56 +00:00
|
|
|
}
|
|
|
|
|
2021-10-15 20:55:03 +00:00
|
|
|
break;
|
|
|
|
}
|
2019-11-17 18:48:56 +00:00
|
|
|
|
2021-10-15 20:55:03 +00:00
|
|
|
case 10:
|
|
|
|
{
|
2021-12-23 16:05:44 +00:00
|
|
|
pActor->spr.cstat &= ~CSTAT_SPRITE_BLOCK_ALL;
|
2021-10-15 20:55:03 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-11-17 18:48:56 +00:00
|
|
|
|
2021-10-15 20:55:03 +00:00
|
|
|
void AIQueen::RadialDamage(RunListEvent* ev)
|
|
|
|
{
|
2021-11-21 18:24:46 +00:00
|
|
|
int nQueen = RunData[ev->nRun].nObjIndex;
|
2021-10-15 20:55:03 +00:00
|
|
|
assert(nQueen >= 0 && nQueen < kMaxQueens);
|
2021-12-07 17:53:02 +00:00
|
|
|
DExhumedActor* pActor = QueenList[nQueen].pActor;
|
|
|
|
if (!pActor) return;
|
2019-11-17 18:48:56 +00:00
|
|
|
|
2021-12-23 18:05:20 +00:00
|
|
|
if (ev->pRadialActor->spr.statnum != 121 && (pActor->spr.cstat & CSTAT_SPRITE_BLOCK_ALL) != 0)
|
2021-10-15 20:55:03 +00:00
|
|
|
{
|
2021-10-26 19:10:51 +00:00
|
|
|
ev->nDamage = runlist_CheckRadialDamage(pActor);
|
2021-10-15 20:55:03 +00:00
|
|
|
if (ev->nDamage) Damage(ev);
|
|
|
|
}
|
|
|
|
}
|
2019-11-17 18:48:56 +00:00
|
|
|
|
2021-10-15 20:55:03 +00:00
|
|
|
void AIQueen::Damage(RunListEvent* ev)
|
|
|
|
{
|
2021-11-21 18:24:46 +00:00
|
|
|
int nQueen = RunData[ev->nRun].nObjIndex;
|
2021-10-15 20:55:03 +00:00
|
|
|
assert(nQueen >= 0 && nQueen < kMaxQueens);
|
2019-11-17 18:48:56 +00:00
|
|
|
|
2021-12-07 17:53:02 +00:00
|
|
|
DExhumedActor* pActor = QueenList[nQueen].pActor;
|
|
|
|
if (!pActor) return;
|
2021-11-21 18:24:46 +00:00
|
|
|
int si = QueenList[nQueen].nAction2;
|
2019-11-17 18:48:56 +00:00
|
|
|
|
2021-10-15 20:55:03 +00:00
|
|
|
if (QueenList[nQueen].nHealth > 0)
|
|
|
|
{
|
|
|
|
QueenList[nQueen].nHealth -= dmgAdjust(ev->nDamage);
|
2019-11-17 18:48:56 +00:00
|
|
|
|
2021-10-15 20:55:03 +00:00
|
|
|
if (QueenList[nQueen].nHealth <= 0)
|
|
|
|
{
|
2021-12-23 16:05:44 +00:00
|
|
|
pActor->spr.xvel = 0;
|
|
|
|
pActor->spr.yvel = 0;
|
|
|
|
pActor->spr.zvel = 0;
|
2019-11-17 18:48:56 +00:00
|
|
|
|
2021-10-20 09:20:49 +00:00
|
|
|
QueenList[nQueen].nAction2++;
|
2019-11-17 18:48:56 +00:00
|
|
|
|
2021-10-20 09:20:49 +00:00
|
|
|
switch (QueenList[nQueen].nAction2)
|
2021-10-15 20:55:03 +00:00
|
|
|
{
|
|
|
|
case 1:
|
|
|
|
QueenList[nQueen].nHealth = 4000;
|
|
|
|
QueenList[nQueen].nAction = 7;
|
2019-11-17 18:48:56 +00:00
|
|
|
|
2022-01-31 22:33:44 +00:00
|
|
|
BuildAnim(nullptr, 36, 0, pActor->int_pos().X, pActor->int_pos().Y, pActor->int_pos().Z - 7680, pActor->sector(), pActor->spr.xrepeat, 4);
|
2021-10-15 20:55:03 +00:00
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
QueenList[nQueen].nHealth = 4000;
|
|
|
|
QueenList[nQueen].nAction = 7;
|
|
|
|
|
|
|
|
DestroyAllEggs();
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
QueenList[nQueen].nAction = 8;
|
|
|
|
QueenList[nQueen].nHealth = 0;
|
2021-10-20 09:20:49 +00:00
|
|
|
QueenList[nQueen].nIndex = 5;
|
2021-10-15 20:55:03 +00:00
|
|
|
|
|
|
|
nCreaturesKilled++;
|
|
|
|
break;
|
2019-11-17 18:48:56 +00:00
|
|
|
}
|
|
|
|
|
2021-10-15 20:55:03 +00:00
|
|
|
QueenList[nQueen].nFrame = 0;
|
2019-11-17 18:48:56 +00:00
|
|
|
}
|
2021-10-15 20:55:03 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
if (si > 0 && !RandomSize(4))
|
|
|
|
{
|
|
|
|
QueenList[nQueen].nAction = 7;
|
|
|
|
QueenList[nQueen].nFrame = 0;
|
|
|
|
}
|
2019-08-31 07:47:15 +00:00
|
|
|
}
|
2021-10-15 20:55:03 +00:00
|
|
|
}
|
2019-08-26 03:59:14 +00:00
|
|
|
}
|
2021-10-15 20:55:03 +00:00
|
|
|
|
|
|
|
void AIQueen::Draw(RunListEvent* ev)
|
|
|
|
{
|
2021-11-21 18:24:46 +00:00
|
|
|
int nQueen = RunData[ev->nRun].nObjIndex;
|
2021-10-15 20:55:03 +00:00
|
|
|
assert(nQueen >= 0 && nQueen < kMaxQueens);
|
2021-11-21 18:24:46 +00:00
|
|
|
int nAction = QueenList[nQueen].nAction;
|
2021-10-17 14:22:25 +00:00
|
|
|
seq_PlotSequence(ev->nParam, SeqOffsets[kSeqQueen] + QueenSeq[nAction].a, QueenList[nQueen].nFrame, QueenSeq[nAction].b);
|
2021-10-15 20:55:03 +00:00
|
|
|
}
|
|
|
|
|
2019-11-22 23:11:37 +00:00
|
|
|
END_PS_NS
|