TombEngine/TR5Main/Objects/TR1/tr1_natla_evil.cpp
TokyoSU 8e148277bf Added Entity
- Lara Evil (Atlantis Version)
- Natla and Evil Natla.
- Larson and Pierre (TR1)
- Raptor (TR1)
2019-12-06 15:26:18 +01:00

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;
}
}