2020-05-27 09:21:20 +02:00
|
|
|
#include "framework.h"
|
|
|
|
#include "tr4_troops.h"
|
|
|
|
#include "box.h"
|
|
|
|
#include "items.h"
|
|
|
|
#include "sphere.h"
|
|
|
|
#include "effect2.h"
|
|
|
|
#include "lara.h"
|
|
|
|
#include "people.h"
|
|
|
|
#include "setup.h"
|
|
|
|
#include "lot.h"
|
|
|
|
#include "level.h"
|
2019-12-05 17:35:57 +01:00
|
|
|
|
|
|
|
BITE_INFO TroopsBite1 = { 0, 300, 64, 7 };
|
|
|
|
|
2020-11-14 15:24:28 +01:00
|
|
|
#define STATE_TROOPS_STOP 1
|
|
|
|
#define STATE_TROOPS_WALK 2
|
|
|
|
#define STATE_TROOPS_RUN 3
|
2021-05-01 16:16:05 +02:00
|
|
|
#define STATE_TROOPS_GUARD 4
|
2020-11-14 15:24:28 +01:00
|
|
|
#define STATE_TROOPS_ATTACK1 5
|
|
|
|
#define STATE_TROOPS_ATTACK2 6
|
|
|
|
#define STATE_TROOPS_DEATH 7
|
|
|
|
#define STATE_TROOPS_AIM1 8
|
|
|
|
#define STATE_TROOPS_AIM2 9
|
|
|
|
#define STATE_TROOPS_AIM3 10
|
|
|
|
#define STATE_TROOPS_ATTACK3 11
|
|
|
|
#define STATE_TROOPS_KILLED_BY_SCORPION 15
|
|
|
|
#define STATE_TROOPS_ATTACKED_BY_SCORPION 16
|
2021-05-01 16:16:05 +02:00
|
|
|
#define STATE_TROOPS_FLASHED 17
|
2019-12-05 17:35:57 +01:00
|
|
|
|
2020-05-27 09:21:20 +02:00
|
|
|
void InitialiseTroops(short itemNumber)
|
2019-12-05 17:35:57 +01:00
|
|
|
{
|
2020-07-21 09:56:47 +02:00
|
|
|
ITEM_INFO* item = &g_Level.Items[itemNumber];
|
2019-12-05 17:35:57 +01:00
|
|
|
|
2020-05-27 09:21:20 +02:00
|
|
|
ClearItem(itemNumber);
|
2019-12-05 17:35:57 +01:00
|
|
|
|
|
|
|
if (item->triggerFlags == 1)
|
|
|
|
{
|
2020-11-14 15:24:28 +01:00
|
|
|
item->goalAnimState = item->currentAnimState = STATE_TROOPS_ATTACKED_BY_SCORPION;
|
2019-12-05 17:35:57 +01:00
|
|
|
item->animNumber = Objects[item->objectNumber].animIndex + 27;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-11-14 15:24:28 +01:00
|
|
|
item->goalAnimState = item->currentAnimState = STATE_TROOPS_STOP;
|
2019-12-05 17:35:57 +01:00
|
|
|
item->animNumber = Objects[item->objectNumber].animIndex + 12;
|
|
|
|
}
|
|
|
|
|
2020-07-21 09:56:47 +02:00
|
|
|
item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
|
2019-12-05 17:35:57 +01:00
|
|
|
}
|
|
|
|
|
2020-05-27 09:21:20 +02:00
|
|
|
void TroopsControl(short itemNumber)
|
2019-12-05 17:35:57 +01:00
|
|
|
{
|
2020-05-27 09:21:20 +02:00
|
|
|
if (!CreatureActive(itemNumber))
|
2019-12-05 17:35:57 +01:00
|
|
|
return;
|
|
|
|
|
2020-07-21 09:56:47 +02:00
|
|
|
ITEM_INFO* item = &g_Level.Items[itemNumber];
|
2019-12-05 17:35:57 +01:00
|
|
|
CREATURE_INFO* creature = (CREATURE_INFO*)item->data;
|
2020-07-07 07:32:33 +02:00
|
|
|
OBJECT_INFO* obj = &Objects[item->objectNumber];
|
2020-11-14 15:24:28 +01:00
|
|
|
|
2019-12-05 17:35:57 +01:00
|
|
|
short angle = 0;
|
|
|
|
short tilt = 0;
|
|
|
|
short joint0 = 0;
|
|
|
|
short joint1 = 0;
|
|
|
|
short joint2 = 0;
|
|
|
|
short rot = 0;
|
2020-11-14 15:24:28 +01:00
|
|
|
|
2019-12-05 17:35:57 +01:00
|
|
|
int dx = 0;
|
|
|
|
int dy = 0;
|
|
|
|
int dz = 0;
|
2020-11-14 15:24:28 +01:00
|
|
|
|
2019-12-05 17:35:57 +01:00
|
|
|
int distance = 0;
|
|
|
|
|
|
|
|
if (item->firedWeapon)
|
|
|
|
{
|
|
|
|
PHD_VECTOR pos;
|
|
|
|
|
|
|
|
pos.x = TroopsBite1.x;
|
|
|
|
pos.y = TroopsBite1.y;
|
|
|
|
pos.z = TroopsBite1.z;
|
|
|
|
|
|
|
|
GetJointAbsPosition(item, &pos, TroopsBite1.meshNum);
|
|
|
|
TriggerDynamicLight(pos.x, pos.y, pos.z, 2 * item->firedWeapon + 8, 24, 16, 4);
|
|
|
|
|
|
|
|
item->firedWeapon--;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (item->hitPoints <= 0)
|
|
|
|
{
|
2020-11-14 15:24:28 +01:00
|
|
|
if (item->currentAnimState != STATE_TROOPS_DEATH
|
|
|
|
&& item->currentAnimState != STATE_TROOPS_KILLED_BY_SCORPION)
|
2019-12-05 17:35:57 +01:00
|
|
|
{
|
2020-11-14 15:24:28 +01:00
|
|
|
if (creature->enemy
|
|
|
|
&& creature->enemy->objectNumber == ID_BIG_SCORPION
|
|
|
|
&& item->itemFlags[0] < 80)
|
2019-12-05 17:35:57 +01:00
|
|
|
{
|
2020-02-24 12:51:28 +01:00
|
|
|
if (creature->enemy->animNumber == Objects[ID_BIG_SCORPION].animIndex + 6)
|
2019-12-05 17:35:57 +01:00
|
|
|
{
|
|
|
|
item->animNumber = Objects[item->objectNumber].animIndex + 23;
|
2020-11-14 15:24:28 +01:00
|
|
|
if (item->currentAnimState == STATE_TROOPS_ATTACKED_BY_SCORPION)
|
2019-12-05 17:35:57 +01:00
|
|
|
{
|
2021-05-13 10:11:22 +02:00
|
|
|
item->frameNumber = g_Level.Anims[item->animNumber].frameBase + 37;
|
2019-12-05 17:35:57 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-07-21 09:56:47 +02:00
|
|
|
item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
|
2019-12-05 17:35:57 +01:00
|
|
|
}
|
2020-11-14 15:24:28 +01:00
|
|
|
item->goalAnimState = STATE_TROOPS_KILLED_BY_SCORPION;
|
|
|
|
item->currentAnimState = STATE_TROOPS_KILLED_BY_SCORPION;
|
2019-12-05 17:35:57 +01:00
|
|
|
|
|
|
|
angle = 0;
|
|
|
|
|
|
|
|
item->pos.xPos = creature->enemy->pos.xPos;
|
|
|
|
item->pos.yPos = creature->enemy->pos.yPos;
|
|
|
|
item->pos.zPos = creature->enemy->pos.zPos;
|
|
|
|
|
|
|
|
item->pos.xRot = creature->enemy->pos.xRot;
|
2021-05-01 16:16:05 +02:00
|
|
|
item->pos.yRot = creature->enemy->pos.yRot;
|
2019-12-05 17:35:57 +01:00
|
|
|
item->pos.zRot = creature->enemy->pos.zRot;
|
|
|
|
|
|
|
|
creature->enemy->triggerFlags = 99;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
angle = 0;
|
|
|
|
item->itemFlags[0]++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
item->animNumber = Objects[item->objectNumber].animIndex + 19;
|
2020-11-14 15:24:28 +01:00
|
|
|
item->currentAnimState = STATE_TROOPS_DEATH;
|
2021-05-07 06:06:30 +02:00
|
|
|
item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
|
2019-12-05 17:35:57 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (item->aiBits)
|
|
|
|
GetAITarget(creature);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Search for active troops
|
|
|
|
creature->enemy = NULL;
|
|
|
|
CREATURE_INFO* baddy = &BaddieSlots[0];
|
|
|
|
int minDistance = 0x7FFFFFFF;
|
|
|
|
|
|
|
|
for (int i = 0; i < NUM_SLOTS; i++)
|
|
|
|
{
|
|
|
|
baddy = &BaddieSlots[i];
|
|
|
|
|
2020-05-27 09:21:20 +02:00
|
|
|
if (baddy->itemNum != NO_ITEM && baddy->itemNum != itemNumber)
|
2019-12-05 17:35:57 +01:00
|
|
|
{
|
2020-07-21 09:56:47 +02:00
|
|
|
ITEM_INFO* currentItem = &g_Level.Items[baddy->itemNum];
|
2019-12-05 17:35:57 +01:00
|
|
|
|
2021-05-01 16:16:05 +02:00
|
|
|
if (currentItem->objectNumber != ID_LARA)
|
2019-12-05 17:35:57 +01:00
|
|
|
{
|
2021-05-01 16:16:05 +02:00
|
|
|
if (currentItem->objectNumber != ID_TROOPS &&
|
|
|
|
(currentItem != LaraItem || creature->hurtByLara))
|
2019-12-05 17:35:57 +01:00
|
|
|
{
|
2021-05-01 16:16:05 +02:00
|
|
|
dx = currentItem->pos.xPos - item->pos.xPos;
|
|
|
|
dy = currentItem->pos.yPos - item->pos.yPos;
|
|
|
|
dz = currentItem->pos.zPos - item->pos.zPos;
|
2021-05-07 06:06:30 +02:00
|
|
|
|
2021-05-01 16:16:05 +02:00
|
|
|
distance = SQUARE(dx) + SQUARE(dy) + SQUARE(dz);
|
|
|
|
|
|
|
|
if (distance < minDistance)
|
|
|
|
{
|
|
|
|
minDistance = distance;
|
|
|
|
creature->enemy = currentItem;
|
|
|
|
}
|
2019-12-05 17:35:57 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-14 15:24:28 +01:00
|
|
|
if (creature->hurtByLara && item->currentAnimState != STATE_TROOPS_ATTACKED_BY_SCORPION)
|
2019-12-05 17:35:57 +01:00
|
|
|
creature->enemy = LaraItem;
|
|
|
|
|
2020-11-14 15:24:28 +01:00
|
|
|
AI_INFO info;
|
2019-12-05 17:35:57 +01:00
|
|
|
CreatureAIInfo(item, &info);
|
|
|
|
|
|
|
|
int distance = 0;
|
|
|
|
if (creature->enemy == LaraItem)
|
|
|
|
{
|
|
|
|
distance = info.distance;
|
|
|
|
rot = info.angle;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
dx = LaraItem->pos.xPos - item->pos.xPos;
|
|
|
|
dz = LaraItem->pos.zPos - item->pos.zPos;
|
2020-11-14 15:24:28 +01:00
|
|
|
distance = SQUARE(dx) + SQUARE(dz);
|
2020-04-25 16:23:53 +02:00
|
|
|
rot = phd_atan(dz, dx) - item->pos.yRot;
|
2019-12-05 17:35:57 +01:00
|
|
|
}
|
|
|
|
|
2020-11-14 15:24:28 +01:00
|
|
|
if (!creature->hurtByLara && creature->enemy == LaraItem)
|
|
|
|
creature->enemy = NULL;
|
|
|
|
|
2019-12-05 17:35:57 +01:00
|
|
|
GetCreatureMood(item, &info, TIMID);
|
2020-11-14 15:24:28 +01:00
|
|
|
CreatureMood(item, &info, TIMID);
|
2019-12-05 17:35:57 +01:00
|
|
|
|
|
|
|
// Vehicle handling
|
2020-04-27 14:01:00 +02:00
|
|
|
if (Lara.Vehicle != NO_ITEM && info.bite)
|
2019-12-05 17:35:57 +01:00
|
|
|
creature->mood == ESCAPE_MOOD;
|
|
|
|
|
|
|
|
angle = CreatureTurn(item, creature->maximumTurn);
|
|
|
|
|
|
|
|
if (item->hitStatus)
|
2020-05-27 09:21:20 +02:00
|
|
|
AlertAllGuards(itemNumber);
|
2019-12-05 17:35:57 +01:00
|
|
|
|
|
|
|
switch (item->currentAnimState)
|
|
|
|
{
|
2020-11-14 15:24:28 +01:00
|
|
|
case STATE_TROOPS_STOP:
|
2019-12-05 17:35:57 +01:00
|
|
|
creature->flags = 0;
|
|
|
|
creature->maximumTurn = 0;
|
|
|
|
joint2 = rot;
|
|
|
|
|
|
|
|
if (item->animNumber == obj->animIndex + 17)
|
|
|
|
{
|
|
|
|
if (abs(info.angle) >= ANGLE(10))
|
|
|
|
{
|
2020-11-14 15:24:28 +01:00
|
|
|
if (info.angle >= 0)
|
2019-12-05 17:35:57 +01:00
|
|
|
{
|
|
|
|
item->pos.yRot += ANGLE(10);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
item->pos.yRot -= ANGLE(10);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
item->pos.yRot += info.angle;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (item->aiBits & GUARD)
|
|
|
|
{
|
|
|
|
joint2 = AIGuard(creature);
|
2021-05-07 06:06:30 +02:00
|
|
|
if (!GetRandomControl())
|
2019-12-05 17:35:57 +01:00
|
|
|
{
|
2020-11-14 15:24:28 +01:00
|
|
|
if (item->currentAnimState == STATE_TROOPS_STOP)
|
2019-12-05 17:35:57 +01:00
|
|
|
{
|
2021-05-01 16:16:05 +02:00
|
|
|
item->goalAnimState = STATE_TROOPS_GUARD;
|
2019-12-05 17:35:57 +01:00
|
|
|
}
|
2021-05-07 06:06:30 +02:00
|
|
|
else
|
|
|
|
{
|
|
|
|
item->goalAnimState = STATE_TROOPS_STOP;
|
|
|
|
}
|
2019-12-05 17:35:57 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (item->aiBits & PATROL1)
|
|
|
|
{
|
2020-11-14 15:24:28 +01:00
|
|
|
item->goalAnimState = STATE_TROOPS_WALK;
|
2019-12-05 17:35:57 +01:00
|
|
|
joint2 = 0;
|
|
|
|
}
|
|
|
|
else if (creature->mood == ESCAPE_MOOD)
|
|
|
|
{
|
2020-11-14 15:24:28 +01:00
|
|
|
item->goalAnimState = STATE_TROOPS_RUN;
|
2019-12-05 17:35:57 +01:00
|
|
|
}
|
|
|
|
else if (Targetable(item, &info))
|
|
|
|
{
|
|
|
|
if (info.distance < SQUARE(3072) || info.zoneNumber != info.enemyZone)
|
|
|
|
{
|
2021-05-07 06:06:30 +02:00
|
|
|
if (GetRandomControl() >= 16384)
|
2019-12-05 17:35:57 +01:00
|
|
|
{
|
2020-11-14 15:24:28 +01:00
|
|
|
item->goalAnimState = STATE_TROOPS_AIM3;
|
2019-12-05 17:35:57 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-11-14 15:24:28 +01:00
|
|
|
item->goalAnimState = STATE_TROOPS_AIM1;
|
2019-12-05 17:35:57 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-11-14 15:24:28 +01:00
|
|
|
item->goalAnimState = STATE_TROOPS_WALK;
|
2019-12-05 17:35:57 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-05-07 06:06:30 +02:00
|
|
|
if ((creature->alerted
|
|
|
|
|| creature->mood != BORED_MOOD)
|
|
|
|
&& (!(item->aiBits & FOLLOW)
|
|
|
|
|| !(item->aiBits & MODIFY)
|
|
|
|
&& distance <= SQUARE(2048)))
|
2019-12-05 17:35:57 +01:00
|
|
|
{
|
|
|
|
if (!creature->mood || info.distance <= SQUARE(2048))
|
|
|
|
{
|
2020-11-14 15:24:28 +01:00
|
|
|
item->goalAnimState = STATE_TROOPS_WALK;
|
2019-12-05 17:35:57 +01:00
|
|
|
break;
|
|
|
|
}
|
2020-11-14 15:24:28 +01:00
|
|
|
item->goalAnimState = STATE_TROOPS_RUN;
|
2019-12-05 17:35:57 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-11-14 15:24:28 +01:00
|
|
|
item->goalAnimState = STATE_TROOPS_STOP;
|
2019-12-05 17:35:57 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
2020-11-14 15:24:28 +01:00
|
|
|
case STATE_TROOPS_WALK:
|
2019-12-05 17:35:57 +01:00
|
|
|
creature->flags = 0;
|
|
|
|
joint2 = rot;
|
|
|
|
creature->maximumTurn = ANGLE(5);
|
|
|
|
|
|
|
|
if (item->aiBits & PATROL1)
|
|
|
|
{
|
2020-11-14 15:24:28 +01:00
|
|
|
item->goalAnimState = STATE_TROOPS_WALK;
|
2019-12-05 17:35:57 +01:00
|
|
|
}
|
2020-11-14 15:24:28 +01:00
|
|
|
else if (creature->mood == ESCAPE_MOOD)
|
2019-12-05 17:35:57 +01:00
|
|
|
{
|
2020-11-14 15:24:28 +01:00
|
|
|
item->goalAnimState = STATE_TROOPS_RUN;
|
2019-12-05 17:35:57 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-05-07 06:06:30 +02:00
|
|
|
if ((item->aiBits & GUARD)
|
|
|
|
|| (item->aiBits & FOLLOW)
|
|
|
|
&& (creature->reachedGoal
|
|
|
|
|| distance > SQUARE(2048)))
|
2019-12-05 17:35:57 +01:00
|
|
|
{
|
2020-11-14 15:24:28 +01:00
|
|
|
item->goalAnimState = STATE_TROOPS_STOP;
|
2019-12-05 17:35:57 +01:00
|
|
|
}
|
2021-05-07 06:06:30 +02:00
|
|
|
else if (Targetable(item, &info))
|
2019-12-05 17:35:57 +01:00
|
|
|
{
|
|
|
|
if (info.distance < SQUARE(3072) || info.enemyZone != info.zoneNumber)
|
|
|
|
{
|
2020-11-14 15:24:28 +01:00
|
|
|
item->goalAnimState = STATE_TROOPS_STOP;
|
2019-12-05 17:35:57 +01:00
|
|
|
}
|
2021-05-07 06:06:30 +02:00
|
|
|
else
|
|
|
|
{
|
|
|
|
item->goalAnimState = STATE_TROOPS_AIM2;
|
|
|
|
}
|
2019-12-05 17:35:57 +01:00
|
|
|
}
|
2021-05-07 06:06:30 +02:00
|
|
|
else if (creature->mood != BORED_MOOD)
|
2019-12-05 17:35:57 +01:00
|
|
|
{
|
|
|
|
if (info.distance > SQUARE(2048))
|
|
|
|
{
|
2020-11-14 15:24:28 +01:00
|
|
|
item->goalAnimState = STATE_TROOPS_RUN;
|
2019-12-05 17:35:57 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (info.ahead)
|
|
|
|
{
|
2020-11-14 15:24:28 +01:00
|
|
|
item->goalAnimState = STATE_TROOPS_STOP;
|
2019-12-05 17:35:57 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
2020-11-14 15:24:28 +01:00
|
|
|
case STATE_TROOPS_RUN:
|
2019-12-05 17:35:57 +01:00
|
|
|
if (info.ahead)
|
|
|
|
{
|
|
|
|
joint2 = info.angle;
|
|
|
|
}
|
|
|
|
creature->maximumTurn = ANGLE(10);
|
|
|
|
tilt = angle / 2;
|
|
|
|
|
2021-05-07 06:06:30 +02:00
|
|
|
if ((item->aiBits & GUARD)
|
|
|
|
|| (item->aiBits & FOLLOW)
|
|
|
|
&& (creature->reachedGoal
|
|
|
|
|| distance > SQUARE(2048)))
|
2019-12-05 17:35:57 +01:00
|
|
|
{
|
2020-11-14 15:24:28 +01:00
|
|
|
item->goalAnimState = STATE_TROOPS_WALK;
|
2019-12-05 17:35:57 +01:00
|
|
|
}
|
2021-05-07 06:06:30 +02:00
|
|
|
else if (creature->mood != ESCAPE_MOOD)
|
2019-12-05 17:35:57 +01:00
|
|
|
{
|
|
|
|
if (Targetable(item, &info))
|
|
|
|
{
|
2020-11-14 15:24:28 +01:00
|
|
|
item->goalAnimState = STATE_TROOPS_WALK;
|
2019-12-05 17:35:57 +01:00
|
|
|
}
|
2021-05-07 06:06:30 +02:00
|
|
|
else if (creature->mood == BORED_MOOD
|
|
|
|
|| creature->mood == STALK_MOOD
|
|
|
|
&& !(item->aiBits & FOLLOW)
|
|
|
|
&& info.distance < SQUARE(2048))
|
2019-12-05 17:35:57 +01:00
|
|
|
{
|
2020-11-14 15:24:28 +01:00
|
|
|
item->goalAnimState = STATE_TROOPS_WALK;
|
2019-12-05 17:35:57 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
2021-05-01 16:16:05 +02:00
|
|
|
case STATE_TROOPS_GUARD:
|
2019-12-05 17:35:57 +01:00
|
|
|
creature->flags = 0;
|
|
|
|
creature->maximumTurn = 0;
|
|
|
|
joint2 = rot;
|
|
|
|
|
|
|
|
if (item->aiBits & GUARD)
|
|
|
|
{
|
|
|
|
joint2 = AIGuard(creature);
|
2021-05-07 06:06:30 +02:00
|
|
|
if (!GetRandomControl())
|
2019-12-05 17:35:57 +01:00
|
|
|
{
|
2020-11-14 15:24:28 +01:00
|
|
|
item->goalAnimState = STATE_TROOPS_STOP;
|
2019-12-05 17:35:57 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (Targetable(item, &info))
|
|
|
|
{
|
2020-11-14 15:24:28 +01:00
|
|
|
item->goalAnimState = STATE_TROOPS_ATTACK1;
|
2019-12-05 17:35:57 +01:00
|
|
|
}
|
2021-05-07 06:06:30 +02:00
|
|
|
else if (creature->mood != BORED_MOOD || !info.ahead)
|
2019-12-05 17:35:57 +01:00
|
|
|
{
|
2020-11-14 15:24:28 +01:00
|
|
|
item->goalAnimState = STATE_TROOPS_STOP;
|
2019-12-05 17:35:57 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
2020-11-14 15:24:28 +01:00
|
|
|
case STATE_TROOPS_ATTACK1:
|
|
|
|
case STATE_TROOPS_ATTACK2:
|
2019-12-05 17:35:57 +01:00
|
|
|
if (info.ahead)
|
|
|
|
{
|
|
|
|
joint0 = info.angle;
|
|
|
|
joint1 = info.xAngle;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (creature->flags)
|
|
|
|
{
|
|
|
|
creature->flags--;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ShotLara(item, &info, &TroopsBite1, joint0, 23);
|
|
|
|
creature->flags = 5;
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
2020-11-14 15:24:28 +01:00
|
|
|
case STATE_TROOPS_AIM1:
|
|
|
|
case STATE_TROOPS_AIM3:
|
2019-12-05 17:35:57 +01:00
|
|
|
creature->flags = 0;
|
|
|
|
|
|
|
|
if (info.ahead)
|
|
|
|
{
|
|
|
|
joint1 = info.xAngle;
|
|
|
|
joint0 = info.angle;
|
|
|
|
|
|
|
|
if (Targetable(item, &info))
|
|
|
|
{
|
2021-05-07 06:06:30 +02:00
|
|
|
item->goalAnimState = item->currentAnimState != STATE_TROOPS_AIM1 ? STATE_TROOPS_ATTACK3 : STATE_TROOPS_ATTACK1;
|
2019-12-05 17:35:57 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-11-14 15:24:28 +01:00
|
|
|
item->goalAnimState = STATE_TROOPS_STOP;
|
2019-12-05 17:35:57 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
2020-11-14 15:24:28 +01:00
|
|
|
case STATE_TROOPS_AIM2:
|
2019-12-05 17:35:57 +01:00
|
|
|
creature->flags = 0;
|
|
|
|
|
|
|
|
if (info.ahead)
|
|
|
|
{
|
|
|
|
joint1 = info.xAngle;
|
|
|
|
joint0 = info.angle;
|
|
|
|
|
|
|
|
if (Targetable(item, &info))
|
|
|
|
{
|
2020-11-14 15:24:28 +01:00
|
|
|
item->goalAnimState = STATE_TROOPS_ATTACK2;
|
2019-12-05 17:35:57 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-11-14 15:24:28 +01:00
|
|
|
item->goalAnimState = STATE_TROOPS_WALK;
|
2019-12-05 17:35:57 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
2020-11-14 15:24:28 +01:00
|
|
|
case STATE_TROOPS_ATTACK3:
|
|
|
|
if (item->goalAnimState != STATE_TROOPS_STOP
|
2019-12-05 17:35:57 +01:00
|
|
|
&& (creature->mood == ESCAPE_MOOD ||
|
|
|
|
info.distance > SQUARE(3072) ||
|
|
|
|
!Targetable(item, &info)))
|
|
|
|
{
|
2020-11-14 15:24:28 +01:00
|
|
|
item->goalAnimState = STATE_TROOPS_STOP;
|
2019-12-05 17:35:57 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (info.ahead)
|
|
|
|
{
|
|
|
|
joint0 = info.angle;
|
|
|
|
joint1 = info.xAngle;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (creature->flags)
|
|
|
|
{
|
|
|
|
creature->flags--;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ShotLara(item, &info, &TroopsBite1, joint0, 23);
|
|
|
|
creature->flags = 5;
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
2020-11-14 15:24:28 +01:00
|
|
|
case STATE_TROOPS_ATTACKED_BY_SCORPION:
|
2019-12-05 17:35:57 +01:00
|
|
|
creature->maximumTurn = 0;
|
|
|
|
break;
|
|
|
|
|
2021-05-01 16:16:05 +02:00
|
|
|
case STATE_TROOPS_FLASHED:
|
2019-12-05 17:35:57 +01:00
|
|
|
if (!WeaponEnemyTimer && !(GetRandomControl() & 0x7F))
|
|
|
|
{
|
2021-05-01 16:16:05 +02:00
|
|
|
item->goalAnimState = STATE_TROOPS_GUARD;
|
2019-12-05 17:35:57 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2021-05-01 16:16:05 +02:00
|
|
|
|
|
|
|
if (WeaponEnemyTimer > 100)
|
|
|
|
{
|
|
|
|
if (item->currentAnimState != STATE_TROOPS_FLASHED
|
|
|
|
&& item->currentAnimState != STATE_TROOPS_ATTACKED_BY_SCORPION)
|
|
|
|
{
|
|
|
|
creature->maximumTurn = 0;
|
|
|
|
item->animNumber = Objects[item->objectNumber].animIndex + 28;
|
|
|
|
item->currentAnimState = STATE_TROOPS_FLASHED;
|
|
|
|
item->frameNumber = g_Level.Anims[item->animNumber].frameBase + (GetRandomControl() & 7);
|
|
|
|
}
|
|
|
|
}
|
2019-12-05 17:35:57 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
CreatureTilt(item, tilt);
|
|
|
|
CreatureJoint(item, 0, joint0);
|
|
|
|
CreatureJoint(item, 1, joint1);
|
|
|
|
CreatureJoint(item, 2, joint2);
|
2020-05-27 09:21:20 +02:00
|
|
|
CreatureAnimation(itemNumber, angle, 0);
|
2018-11-28 20:51:20 +01:00
|
|
|
}
|