TombEngine/TR5Main/Objects/TR3/tr3_mpstick.cpp
TokyoSU 7432353bed Restructured the Entity Files
- Moved GetWaterSurface to Control.cpp.
- Added mineL/mineR in LaraExtraInfo.
2019-12-05 17:35:57 +01:00

502 lines
No EOL
12 KiB
C++

#include "../newobjects.h"
#include "../../Game/Box.h"
#include "../../Game/effects.h"
#include "../../Game/people.h"
BITE_INFO mpstickBite1 = { 247, 10, 11, 13 };
BITE_INFO mpstickBite2 = { 0, 0, 100, 6 };
typedef enum MPSTICK_STATES {
BATON_EMPTY,
BATON_STOP,
BATON_WALK,
BATON_PUNCH2,
BATON_AIM2,
BATON_WAIT,
BATON_AIM1,
BATON_AIM0,
BATON_PUNCH1,
BATON_PUNCH0,
BATON_RUN,
BATON_DEATH,
BATON_KICK,
BATON_CLIMB3,
BATON_CLIMB1,
BATON_CLIMB2,
BATON_FALL3
};
void InitialiseMPStick(short itemNumber)
{
ITEM_INFO* item = &Items[itemNumber];
InitialiseCreature(itemNumber);
item->animNumber = Objects[ID_MP_WITH_STICK].animIndex + 6;
item->frameNumber = Anims[item->animNumber].frameBase;
item->currentAnimState = item->goalAnimState = BATON_STOP;
}
void MPStickControl(short itemNumber)
{
if (!CreatureActive(itemNumber))
return;
ITEM_INFO* item = &Items[itemNumber];
CREATURE_INFO* creature = (CREATURE_INFO*)item->data;
short torsoY = 0;
short torsoX = 0;
short head = 0;
short angle = 0;
short tilt = 0;
if (Boxes[item->boxNumber].overlapIndex & BLOCKED)
{
DoLotsOfBlood(item->pos.xPos, item->pos.yPos - (GetRandomControl() & 255) - 32, item->pos.zPos, (GetRandomControl() & 127) + 128, GetRandomControl() << 1, item->roomNumber, 3);
item->hitPoints -= 20;
}
int dx;
int dz;
int x;
int y;
int z;
AI_INFO info;
AI_INFO laraInfo;
ITEM_INFO* target;
ITEM_INFO* enemy;
if (item->hitPoints <= 0)
{
if (item->currentAnimState != BATON_DEATH)
{
item->animNumber = Objects[ID_MP_WITH_STICK].animIndex + 26;
item->frameNumber = Anims[item->animNumber].frameBase;
item->currentAnimState = BATON_DEATH;
creature->LOT.step = 256;
}
}
else
{
if (item->aiBits)
GetAITarget(creature);
else
{
creature->enemy = LaraItem;
dx = LaraItem->pos.xPos - item->pos.xPos;
dz = LaraItem->pos.zPos - item->pos.zPos;
laraInfo.distance = SQUARE(dx) + SQUARE(dx);
int bestDistance = 0x7fffffff;
CREATURE_INFO* currentCreature = BaddieSlots;
for (int slot = 0; slot < NUM_SLOTS; slot++, currentCreature++)
{
if (currentCreature->itemNum == NO_ITEM || currentCreature->itemNum == itemNumber)
continue;
target = &Items[currentCreature->itemNum];
if (target->objectNumber != ID_LARA /*&& target->objectNumber != ID_BOB*/)
continue;
dx = target->pos.xPos - item->pos.xPos;
dz = target->pos.zPos - item->pos.zPos;
if (dz > 32000 || dz < -32000 || dx > 32000 || dx < -32000)
continue;
int distance = SQUARE(dx) + SQUARE(dz);
if (distance < bestDistance && distance < laraInfo.distance)
{
bestDistance = distance;
creature->enemy = target;
}
}
}
CreatureAIInfo(item, &info);
if (creature->enemy == LaraItem)
{
laraInfo.angle = info.angle;
laraInfo.distance = info.distance;
}
else
{
dx = LaraItem->pos.xPos - item->pos.xPos;
dz = LaraItem->pos.zPos - item->pos.zPos;
laraInfo.angle = ATAN(dz, dx) - item->pos.yRot;
laraInfo.distance = SQUARE(dx) + SQUARE(dz);
}
GetCreatureMood(item, &info, VIOLENT);
CreatureMood(item, &info, VIOLENT);
angle = CreatureTurn(item, creature->maximumTurn);
enemy = creature->enemy;
creature->enemy = LaraItem;
if (item->hitStatus || ((laraInfo.distance < SQUARE(1024) || TargetVisible(item, &laraInfo)) && (abs(LaraItem->pos.yPos - item->pos.yPos) < 1024))) // TS- TODO: take this back out after demo!!
{
if (!creature->alerted)
SoundEffect(SFX_TR3_AMERCAN_HOY_ID300, &item->pos, 0);
AlertAllGuards(itemNumber);
}
creature->enemy = enemy;
switch (item->currentAnimState)
{
case BATON_WAIT:
if (creature->alerted || item->goalAnimState == BATON_RUN)
{
item->goalAnimState = BATON_STOP;
break;
}
case BATON_STOP:
creature->flags = 0;
creature->maximumTurn = 0;
head = laraInfo.angle;
if (item->aiBits & GUARD)
{
head = AIGuard(creature);
if (!(GetRandomControl() & 0xFF))
{
if (item->currentAnimState == BATON_STOP)
item->goalAnimState = BATON_WAIT;
else
item->goalAnimState = BATON_STOP;
}
break;
}
else if (item->aiBits & PATROL1)
item->goalAnimState = BATON_WALK;
else if (creature->mood == ESCAPE_MOOD)
{
if (Lara.target != item && info.ahead && !item->hitStatus)
item->goalAnimState = BATON_STOP;
else
item->goalAnimState = BATON_RUN;
}
else if (creature->mood == BORED_MOOD || ((item->aiBits & FOLLOW) && (creature->reachedGoal || laraInfo.distance > SQUARE(2048))))
{
if (item->requiredAnimState)
item->goalAnimState = item->requiredAnimState;
else if (info.ahead)
item->goalAnimState = BATON_STOP;
else
item->goalAnimState = BATON_RUN;
}
else if (info.bite && info.distance < SQUARE(512))
item->goalAnimState = BATON_AIM0;
else if (info.bite && info.distance < SQUARE(1024))
item->goalAnimState = BATON_AIM1;
else if (info.bite && info.distance < SQUARE(1024))
item->goalAnimState = BATON_WALK;
else
item->goalAnimState = BATON_RUN;
break;
case BATON_WALK:
head = laraInfo.angle;
creature->flags = 0;
creature->maximumTurn = ANGLE(6);
if (item->aiBits & PATROL1)
{
item->goalAnimState = BATON_WALK;
head = 0;
}
else if (creature->mood == ESCAPE_MOOD)
item->goalAnimState = BATON_RUN;
else if (creature->mood == BORED_MOOD)
{
if (GetRandomControl() < 0x100)
{
item->requiredAnimState = BATON_WAIT;
item->goalAnimState = BATON_STOP;
}
}
else if (info.bite && info.distance < SQUARE(1536) && info.xAngle < 0)
item->goalAnimState = BATON_KICK;
else if (info.bite && info.distance < SQUARE(512))
item->goalAnimState = BATON_STOP;
else if (info.bite && info.distance < SQUARE(1280))
item->goalAnimState = BATON_AIM2;
else
item->goalAnimState = BATON_RUN;
break;
case BATON_RUN:
if (info.ahead)
head = info.angle;
creature->maximumTurn = ANGLE(7);
tilt = angle / 2;
if (item->aiBits & GUARD)
item->goalAnimState = BATON_WAIT;
else if (creature->mood == ESCAPE_MOOD)
{
if (Lara.target != item && info.ahead)
item->goalAnimState = BATON_STOP;
break;
}
else if ((item->aiBits & FOLLOW) && (creature->reachedGoal || laraInfo.distance > SQUARE(2048)))
item->goalAnimState = BATON_STOP;
else if (creature->mood == BORED_MOOD)
item->goalAnimState = BATON_WALK;
else if (info.ahead && info.distance < SQUARE(1024))
item->goalAnimState = BATON_WALK;
break;
case BATON_AIM0:
if (info.ahead)
{
torsoY = info.angle;
torsoX = info.xAngle;
}
creature->maximumTurn = ANGLE(6);
creature->flags = 0;
if (info.bite && info.distance < SQUARE(512))
item->goalAnimState = BATON_PUNCH0;
else
item->goalAnimState = BATON_STOP;
break;
case BATON_AIM1:
if (info.ahead)
{
torsoY = info.angle;
torsoX = info.xAngle;
}
creature->maximumTurn = ANGLE(6);
creature->flags = 0;
if (info.ahead && info.distance < SQUARE(1024))
item->goalAnimState = BATON_PUNCH1;
else
item->goalAnimState = BATON_STOP;
break;
case BATON_AIM2:
if (info.ahead)
{
torsoY = info.angle;
torsoX = info.xAngle;
}
creature->maximumTurn = ANGLE(6);
creature->flags = 0;
if (info.bite && info.distance < SQUARE(1280))
item->goalAnimState = BATON_PUNCH2;
else
item->goalAnimState = BATON_WALK;
break;
case BATON_PUNCH0:
if (info.ahead)
{
torsoY = info.angle;
torsoX = info.xAngle;
}
creature->maximumTurn = ANGLE(6);
if (enemy == LaraItem)
{
if (!creature->flags && (item->touchBits & 0x2400))
{
LaraItem->hitPoints -= 80;
LaraItem->hitStatus = 1;
CreatureEffect(item, &mpstickBite1, DoBloodSplat);
SoundEffect(SFX_LARA_THUD, &item->pos, 0);
creature->flags = 1;
}
}
else
{
if (!creature->flags && enemy)
{
if (abs(enemy->pos.xPos - item->pos.xPos) < 256 &&
abs(enemy->pos.yPos - item->pos.yPos) <= 256 &&
abs(enemy->pos.zPos - item->pos.zPos) < 256)
{
enemy->hitPoints -= 80 >> 4;
enemy->hitStatus = 1;
creature->flags = 1;
CreatureEffect(item, &mpstickBite1, DoBloodSplat);
SoundEffect(SFX_LARA_THUD, &item->pos, 0);
}
}
}
break;
case BATON_PUNCH1:
if (info.ahead)
{
torsoY = info.angle;
torsoX = info.xAngle;
}
creature->maximumTurn = ANGLE(6);
if (enemy == LaraItem)
{
if (!creature->flags && (item->touchBits & 0x2400))
{
LaraItem->hitPoints -= 80;
LaraItem->hitStatus = 1;
CreatureEffect(item, &mpstickBite1, DoBloodSplat);
SoundEffect(SFX_LARA_THUD, &item->pos, 0);
creature->flags = 1;
}
}
else
{
if (!creature->flags && enemy)
{
if (abs(enemy->pos.xPos - item->pos.xPos) < 256 &&
abs(enemy->pos.yPos - item->pos.yPos) <= 256 &&
abs(enemy->pos.zPos - item->pos.zPos) < 256)
{
enemy->hitPoints -= 80 >> 4;
enemy->hitStatus = 1;
creature->flags = 1;
CreatureEffect(item, &mpstickBite1, DoBloodSplat);
SoundEffect(SFX_LARA_THUD, &item->pos, 0);
}
}
}
if (info.ahead && info.distance > SQUARE(1024) && info.distance < SQUARE(1280))
item->goalAnimState = BATON_PUNCH2;
break;
case BATON_PUNCH2:
if (info.ahead)
{
torsoY = info.angle;
torsoX = info.xAngle;
}
creature->maximumTurn = ANGLE(6);
if (enemy == LaraItem)
{
if (creature->flags != 2 && (item->touchBits & 0x2400))
{
LaraItem->hitPoints -= 100;
LaraItem->hitStatus = 1;
CreatureEffect(item, &mpstickBite1, DoBloodSplat);
creature->flags = 2;
SoundEffect(70, &item->pos, 0);
}
}
else
{
if (creature->flags != 2 && enemy)
{
if (abs(enemy->pos.xPos - item->pos.xPos) < 256 &&
abs(enemy->pos.yPos - item->pos.yPos) <= 256 &&
abs(enemy->pos.zPos - item->pos.zPos) < 256)
{
enemy->hitPoints -= 100 >> 4;
enemy->hitStatus = 1;
creature->flags = 2;
CreatureEffect(item, &mpstickBite1, DoBloodSplat);
SoundEffect(SFX_LARA_THUD, &item->pos, 0);
}
}
}
break;
case BATON_KICK:
if (info.ahead)
{
torsoY = info.angle;
}
creature->maximumTurn = ANGLE(6);
if (enemy == LaraItem)
{
if (creature->flags != 1 && (item->touchBits & 0x60) && (item->frameNumber > Anims[item->animNumber].frameBase + 8))
{
LaraItem->hitPoints -= 150;
LaraItem->hitStatus = 1;
CreatureEffect(item, &mpstickBite2, DoBloodSplat);
SoundEffect(SFX_LARA_THUD, &item->pos, 0);
creature->flags = 1;
}
}
else
{
if (!creature->flags != 1 && enemy && (item->frameNumber > Anims[item->animNumber].frameBase + 8))
{
if (abs(enemy->pos.xPos - item->pos.xPos) < 256 &&
abs(enemy->pos.yPos - item->pos.yPos) <= 256 &&
abs(enemy->pos.zPos - item->pos.zPos) < 256)
{
enemy->hitPoints -= 150 >> 4;
enemy->hitStatus = 1;
creature->flags = 1;
CreatureEffect(item, &mpstickBite2, DoBloodSplat);
SoundEffect(SFX_LARA_THUD, &item->pos, 0);
}
}
}
break;
}
}
CreatureTilt(item, tilt);
CreatureJoint(item, 0, torsoY);
CreatureJoint(item, 1, torsoX);
CreatureJoint(item, 2, head);
if (item->currentAnimState < BATON_DEATH)
{
switch (CreatureVault(itemNumber, angle, 2, 260))
{
case 2:
creature->maximumTurn = 0;
item->animNumber = Objects[ID_MP_WITH_STICK].animIndex + 28;
item->frameNumber = Anims[item->animNumber].frameBase;
item->currentAnimState = BATON_CLIMB1;
break;
case 3:
creature->maximumTurn = 0;
item->animNumber = Objects[ID_MP_WITH_STICK].animIndex + 29;
item->frameNumber = Anims[item->animNumber].frameBase;
item->currentAnimState = BATON_CLIMB2;
break;
case 4:
creature->maximumTurn = 0;
item->animNumber = Objects[ID_MP_WITH_STICK].animIndex + 27;
item->frameNumber = Anims[item->animNumber].frameBase;
item->currentAnimState = BATON_CLIMB3;
break;
case -4:
creature->maximumTurn = 0;
item->animNumber = Objects[ID_MP_WITH_STICK].animIndex + 30;
item->frameNumber = Anims[item->animNumber].frameBase;
item->currentAnimState = BATON_FALL3;
break;
}
}
else
{
creature->maximumTurn = 0;
CreatureAnimation(itemNumber, angle, tilt);
}
}