mirror of
https://github.com/TombEngine/TombEngine.git
synced 2025-05-01 09:18:00 +03:00

- Lara Evil (Atlantis Version) - Natla and Evil Natla. - Larson and Pierre (TR1) - Raptor (TR1)
222 lines
No EOL
5.8 KiB
C++
222 lines
No EOL
5.8 KiB
C++
#include "../newobjects.h"
|
|
#include "../../Game/Box.h"
|
|
#include "../../Game/effect2.h"
|
|
#include "../../Game/items.h"
|
|
|
|
enum abortion_anims {
|
|
ABORT_EMPTY, ABORT_STOP, ABORT_TURNL, ABORT_TURNR, ABORT_ATTACK1, ABORT_ATTACK2,
|
|
ABORT_ATTACK3, ABORT_FORWARD, ABORT_SET, ABORT_FALL, ABORT_DEATH, ABORT_KILL
|
|
};
|
|
|
|
#define ABORT_NEED_TURN ANGLE(45)
|
|
#define ABORT_TURN ANGLE(3)
|
|
#define ABORT_ATTACK_RANGE SQUARE(2600)
|
|
#define ABORT_CLOSE_RANGE SQUARE(2250)
|
|
#define ABORT_ATTACK1_CHANCE 11000
|
|
#define ABORT_ATTACK2_CHANCE 22000
|
|
#define ABORT_TLEFT 0x7ff0
|
|
#define ABORT_TRIGHT 0x3ff8000
|
|
#define ABORT_TOUCH (ABORT_TLEFT|ABORT_TRIGHT)
|
|
#define ABORT_PART_DAMAGE 250
|
|
#define ABORT_ATTACK_DAMAGE 500
|
|
#define ABORT_TOUCH_DAMAGE 5
|
|
#define ABORT_DIE_ANIM 13
|
|
|
|
void NatlaEvilControl(short itemNum)
|
|
{
|
|
if (!CreatureActive(itemNum))
|
|
return;
|
|
|
|
ITEM_INFO* item;
|
|
CREATURE_INFO* abort;
|
|
AI_INFO info;
|
|
FLOOR_INFO* floor;
|
|
short head, angle;
|
|
|
|
item = &Items[itemNum];
|
|
abort = (CREATURE_INFO*)item->data;
|
|
head = angle = 0;
|
|
|
|
/* Has abortion been killed? */
|
|
if (item->hitPoints <= 0)
|
|
{
|
|
if (item->currentAnimState != ABORT_DEATH)
|
|
{
|
|
item->animNumber = Objects[item->objectNumber].animIndex + ABORT_DIE_ANIM;
|
|
item->frameNumber = Anims[item->animNumber].frameBase;
|
|
item->currentAnimState = ABORT_DEATH;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
CreatureAIInfo(item, &info);
|
|
|
|
if (info.ahead)
|
|
head = info.angle;
|
|
|
|
GetCreatureMood(item, &info, VIOLENT);
|
|
CreatureMood(item, &info, VIOLENT);
|
|
|
|
/* Work out required turn */
|
|
angle = (short)ATAN(abort->target.z - item->pos.zPos, abort->target.x - item->pos.xPos) - item->pos.yRot;
|
|
|
|
/* Touch damage */
|
|
if (item->touchBits)
|
|
{
|
|
LaraItem->hitPoints -= ABORT_TOUCH_DAMAGE;
|
|
LaraItem->hitStatus = true;
|
|
}
|
|
|
|
switch (item->currentAnimState)
|
|
{
|
|
case ABORT_SET:
|
|
item->goalAnimState = ABORT_FALL;
|
|
item->gravityStatus = true;
|
|
break;
|
|
|
|
case ABORT_STOP:
|
|
if (LaraItem->hitPoints <= 0)
|
|
break;
|
|
|
|
abort->flags = 0;
|
|
if (angle > ABORT_NEED_TURN)
|
|
item->goalAnimState = ABORT_TURNR;
|
|
else if (angle < -ABORT_NEED_TURN)
|
|
item->goalAnimState = ABORT_TURNL;
|
|
else if (info.distance < ABORT_ATTACK_RANGE)
|
|
{
|
|
/* If Lara is gonna get killed by this, do it the pretty way */
|
|
if (LaraItem->hitPoints <= ABORT_ATTACK_DAMAGE)
|
|
{
|
|
if (info.distance < ABORT_CLOSE_RANGE)
|
|
item->goalAnimState = ABORT_ATTACK3;
|
|
else
|
|
item->goalAnimState = ABORT_FORWARD;
|
|
}
|
|
else if (GetRandomControl() < 0x4000)
|
|
item->goalAnimState = ABORT_ATTACK1;
|
|
else
|
|
item->goalAnimState = ABORT_ATTACK2;
|
|
}
|
|
else
|
|
item->goalAnimState = ABORT_FORWARD;
|
|
break;
|
|
|
|
case ABORT_FORWARD:
|
|
if (angle < -ABORT_TURN)
|
|
item->goalAnimState -= ABORT_TURN;
|
|
else if (angle > ABORT_TURN)
|
|
item->goalAnimState += ABORT_TURN;
|
|
else
|
|
item->goalAnimState += angle;
|
|
|
|
if (angle > ABORT_NEED_TURN || angle < -ABORT_NEED_TURN)
|
|
item->goalAnimState = ABORT_STOP;
|
|
else if (info.distance < ABORT_ATTACK_RANGE)
|
|
item->goalAnimState = ABORT_STOP;
|
|
break;
|
|
|
|
case ABORT_TURNR:
|
|
/* Turn 27 degrees to right (only turning when abortion pushes with hands) */
|
|
if (!abort->flags)
|
|
abort->flags = item->frameNumber;
|
|
else if (item->frameNumber - abort->flags > 16 && item->frameNumber - abort->flags < 23)
|
|
item->pos.yRot += ANGLE(14);
|
|
|
|
if (angle < ABORT_NEED_TURN)
|
|
item->goalAnimState = ABORT_STOP;
|
|
break;
|
|
|
|
case ABORT_TURNL:
|
|
/* Turn 27 degrees to left (only turning when abortion pushes with hands) */
|
|
if (!abort->flags)
|
|
abort->flags = item->frameNumber;
|
|
else if (item->frameNumber - abort->flags > 13 && item->frameNumber - abort->flags < 23)
|
|
item->pos.yRot -= ANGLE(9);
|
|
|
|
if (angle > -ABORT_NEED_TURN)
|
|
item->goalAnimState = ABORT_STOP;
|
|
break;
|
|
|
|
case ABORT_ATTACK1:
|
|
if (!abort->flags && (item->touchBits & ABORT_TRIGHT))
|
|
{
|
|
LaraItem->hitPoints -= ABORT_ATTACK_DAMAGE;
|
|
LaraItem->hitStatus = true;
|
|
abort->flags = 1;
|
|
}
|
|
break;
|
|
|
|
case ABORT_ATTACK2:
|
|
if (!abort->flags && (item->touchBits & ABORT_TOUCH))
|
|
{
|
|
LaraItem->hitPoints -= ABORT_ATTACK_DAMAGE;
|
|
LaraItem->hitStatus = true;
|
|
abort->flags = 1;
|
|
}
|
|
break;
|
|
|
|
case ABORT_ATTACK3:
|
|
if (item->touchBits & ABORT_TRIGHT || LaraItem->hitPoints <= 0)
|
|
{
|
|
item->goalAnimState = ABORT_KILL;
|
|
|
|
LaraItem->animNumber = Objects[ID_LARA_EXTRA_ANIMS].animIndex;
|
|
LaraItem->frameNumber = Anims[LaraItem->animNumber].frameBase;
|
|
LaraItem->currentAnimState = LaraItem->goalAnimState = 46;
|
|
LaraItem->roomNumber = item->roomNumber;
|
|
LaraItem->pos.xPos = item->pos.xPos;
|
|
LaraItem->pos.yPos = item->pos.yPos;
|
|
LaraItem->pos.zPos = item->pos.zPos;
|
|
LaraItem->pos.yRot = item->pos.yRot;
|
|
LaraItem->pos.xRot = LaraItem->pos.zRot = 0;
|
|
LaraItem->gravityStatus = false;
|
|
LaraItem->hitPoints = -1;
|
|
Lara.air = -1;
|
|
Lara.gunStatus = LG_HANDS_BUSY;
|
|
Lara.gunType = WEAPON_NONE;
|
|
|
|
Camera.targetDistance = WALL_SIZE * 2;
|
|
Camera.flags = FOLLOW_CENTRE;
|
|
}
|
|
break;
|
|
|
|
case ABORT_KILL:
|
|
Camera.targetDistance = WALL_SIZE * 2;
|
|
Camera.flags = FOLLOW_CENTRE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
CreatureJoint(item, 0, head);
|
|
|
|
/* Actually do animation allowing for collisions */
|
|
if (item->currentAnimState == ABORT_FALL)
|
|
{
|
|
AnimateItem(item);
|
|
|
|
if (item->pos.yPos > item->floor)
|
|
{
|
|
item->goalAnimState = ABORT_STOP;
|
|
item->gravityStatus = false;
|
|
item->pos.yPos = item->floor;
|
|
Camera.bounce = 500;
|
|
}
|
|
}
|
|
else
|
|
CreatureAnimation(itemNum, 0, 0);
|
|
|
|
/* Explode on death and set off heavy trigger into the bargain */
|
|
if (item->status == ITEM_DEACTIVATED)
|
|
{
|
|
SoundEffect(171, &item->pos, NULL);
|
|
ExplodingDeath(itemNum, 0xffffffff, ABORT_PART_DAMAGE);
|
|
|
|
floor = GetFloor(item->pos.xPos, item->pos.yPos, item->pos.zPos, &item->roomNumber);
|
|
GetFloorHeight(floor, item->pos.xPos, item->pos.yPos, item->pos.zPos);
|
|
TestTriggers(TriggerIndex, TRUE, 0);
|
|
|
|
KillItem(itemNum);
|
|
item->status = ITEM_DEACTIVATED;
|
|
}
|
|
} |