TombEngine/TR5Main/Objects/TR1/Entity/tr1_bear.cpp

273 lines
5.3 KiB
C++
Raw Normal View History

#include "framework.h"
#include "tr1_bear.h"
#include "box.h"
#include "effects\effects.h"
#include "setup.h"
#include "level.h"
#include "control.h"
#include "lara.h"
2021-08-29 10:04:49 +02:00
#include "creature_info.h"
2021-08-28 13:27:58 +02:00
#include "control.h"
BITE_INFO bearBite = { 0, 96, 335, 14 };
2020-11-12 23:47:48 -06:00
enum bearStates{
BEAR_STROLL,
BEAR_STOP,
BEAR_WALK,
BEAR_RUN,
BEAR_REAR,
BEAR_ROAR,
BEAR_ATTACK1,
BEAR_ATTACK2,
BEAR_EAT,
BEAR_DEATH
};
#define TOUCH 0x2406C
#define ROAR_CHANCE 0x50
#define REAR_CHANCE 0x300
#define DROP_CHANCE 0x600
#define REAR_RANGE SQUARE(WALL_SIZE*2)
#define ATTACK_RANGE SQUARE(WALL_SIZE)
#define PAT_RANGE SQUARE(600)
#define RUN_TURN ANGLE(5)
#define WALK_TURN ANGLE(2)
#define EAT_RANGE SQUARE(WALL_SIZE*3/4)
#define CHARGE_DAMAGE 3
#define SLAM_DAMAGE 200
#define ATTACK_DAMAGE 200
#define PAT_DAMAGE 400
void BearControl(short itemNum)
{
if (!CreatureActive(itemNum))
return;
ITEM_INFO* item = &g_Level.Items[itemNum];
CREATURE_INFO* creature = (CREATURE_INFO*)item->data;
short head = 0;
2020-11-12 23:47:48 -06:00
short angle;
if (item->hitPoints <= 0)
{
2021-03-24 20:06:37 +01:00
angle = CreatureTurn(item, ANGLE(1));
2021-03-24 20:06:37 +01:00
switch (item->currentAnimState)
{
2020-11-12 23:47:48 -06:00
case BEAR_WALK:
{
item->goalAnimState = BEAR_REAR;
break;
2020-11-12 23:47:48 -06:00
}
case BEAR_RUN:
case BEAR_STROLL:
{
item->goalAnimState = BEAR_STOP;
break;
2020-11-12 23:47:48 -06:00
}
case BEAR_REAR:
{
creature->flags = 1;
2020-11-12 23:47:48 -06:00
item->goalAnimState = BEAR_DEATH;
break;
2020-11-12 23:47:48 -06:00
}
case BEAR_STOP:
{
creature->flags = 0;
2020-11-12 23:47:48 -06:00
item->goalAnimState = BEAR_DEATH;
break;
2020-11-12 23:47:48 -06:00
}
case BEAR_DEATH:
{
if (creature->flags && (item->touchBits & TOUCH))
{
2020-11-12 23:47:48 -06:00
LaraItem->hitPoints -= SLAM_DAMAGE;
LaraItem->hitStatus = 1;
creature->flags = 0;
}
break;
}
2021-03-24 20:06:37 +01:00
}
}
else
{
AI_INFO info;
CreatureAIInfo(item, &info);
if (info.ahead)
head = info.angle;
GetCreatureMood(item, &info, VIOLENT);
CreatureMood(item, &info, VIOLENT);
angle = CreatureTurn(item, creature->maximumTurn);
if (item->hitStatus)
creature->flags = 1;
2020-11-12 23:47:48 -06:00
const bool Laradead = (LaraItem->hitPoints <= 0);
switch (item->currentAnimState)
{
2020-11-12 23:47:48 -06:00
case BEAR_STOP:
if (Laradead)
{
2020-11-12 23:47:48 -06:00
if (info.bite && info.distance < EAT_RANGE)
{
2020-11-12 23:47:48 -06:00
item->goalAnimState = BEAR_EAT;
}
else
{
2020-11-12 23:47:48 -06:00
item->goalAnimState = BEAR_STROLL;
}
}
else if (item->requiredAnimState)
{
item->goalAnimState = item->requiredAnimState;
}
else if (creature->mood == BORED_MOOD)
{
2020-11-12 23:47:48 -06:00
item->goalAnimState = BEAR_STROLL;
}
else
{
2020-11-12 23:47:48 -06:00
item->goalAnimState = BEAR_RUN;
}
break;
2020-11-12 23:47:48 -06:00
case BEAR_STROLL:
creature->maximumTurn = WALK_TURN;
2020-11-12 23:47:48 -06:00
if (Laradead && (item->touchBits & TOUCH) && info.ahead)
{
2020-11-12 23:47:48 -06:00
item->goalAnimState = BEAR_STOP;
}
else if (creature->mood != BORED_MOOD)
{
2020-11-12 23:47:48 -06:00
item->goalAnimState = BEAR_STOP;
if (creature->mood == ESCAPE_MOOD)
{
2020-11-12 23:47:48 -06:00
item->requiredAnimState = BEAR_STROLL;
}
}
2020-11-12 23:47:48 -06:00
else if (GetRandomControl() < ROAR_CHANCE)
{
2020-11-12 23:47:48 -06:00
item->requiredAnimState = BEAR_ROAR;
item->goalAnimState = BEAR_STOP;
}
break;
2020-11-12 23:47:48 -06:00
case BEAR_RUN:
creature->maximumTurn = RUN_TURN;
2020-11-12 23:47:48 -06:00
if (item->touchBits & TOUCH)
{
2020-11-12 23:47:48 -06:00
LaraItem->hitPoints -= CHARGE_DAMAGE;
LaraItem->hitStatus = true;
}
2020-11-12 23:47:48 -06:00
if (creature->mood == BORED_MOOD || Laradead)
{
2020-11-12 23:47:48 -06:00
item->goalAnimState = BEAR_STOP;
}
else if (info.ahead && !item->requiredAnimState)
{
2020-11-12 23:47:48 -06:00
if (!creature->flags && info.distance < REAR_RANGE && GetRandomControl() < REAR_CHANCE)
{
2020-11-12 23:47:48 -06:00
item->requiredAnimState = BEAR_REAR;
item->goalAnimState = BEAR_STOP;
}
2020-11-12 23:47:48 -06:00
else if (info.distance < ATTACK_RANGE)
{
2020-11-12 23:47:48 -06:00
item->goalAnimState = BEAR_ATTACK1;
}
}
break;
2020-11-12 23:47:48 -06:00
case BEAR_REAR:
if (creature->flags)
{
2020-11-12 23:47:48 -06:00
item->requiredAnimState = BEAR_STROLL;
item->goalAnimState = BEAR_STOP;
}
else if (item->requiredAnimState)
{
item->goalAnimState = item->requiredAnimState;
}
else if (creature->mood == BORED_MOOD || creature->mood == ESCAPE_MOOD)
{
2020-11-12 23:47:48 -06:00
item->goalAnimState = BEAR_STOP;
}
2020-11-12 23:47:48 -06:00
else if (info.bite && info.distance < PAT_RANGE)
{
2020-11-12 23:47:48 -06:00
item->goalAnimState = BEAR_ATTACK2;
}
else
{
2020-11-12 23:47:48 -06:00
item->goalAnimState = BEAR_WALK;
}
break;
2020-11-12 23:47:48 -06:00
case BEAR_WALK:
if (creature->flags)
{
2020-11-12 23:47:48 -06:00
item->requiredAnimState = BEAR_STROLL;
item->goalAnimState = BEAR_REAR;
}
2020-11-12 23:47:48 -06:00
else if (info.ahead && (item->touchBits & TOUCH))
{
2020-11-12 23:47:48 -06:00
item->goalAnimState = BEAR_REAR;
}
else if (creature->mood == ESCAPE_MOOD)
{
2020-11-12 23:47:48 -06:00
item->goalAnimState = BEAR_REAR;
item->requiredAnimState = BEAR_STROLL;
}
2020-11-12 23:47:48 -06:00
else if (creature->mood == BORED_MOOD || GetRandomControl() < ROAR_CHANCE)
{
2020-11-12 23:47:48 -06:00
item->requiredAnimState = BEAR_ROAR;
item->goalAnimState = BEAR_REAR;
}
2020-11-12 23:47:48 -06:00
else if (info.distance > REAR_RANGE || GetRandomControl() < DROP_CHANCE)
{
2020-11-12 23:47:48 -06:00
item->requiredAnimState = BEAR_STOP;
item->goalAnimState = BEAR_REAR;
}
break;
2020-11-12 23:47:48 -06:00
case BEAR_ATTACK2:
if (!item->requiredAnimState && (item->touchBits & TOUCH))
{
2020-11-12 23:47:48 -06:00
LaraItem->hitPoints -= PAT_DAMAGE;
LaraItem->hitStatus = true;
2020-11-12 23:47:48 -06:00
item->requiredAnimState = BEAR_REAR;
}
break;
2020-11-12 23:47:48 -06:00
case BEAR_ATTACK1:
if (!item->requiredAnimState && (item->touchBits & TOUCH))
{
CreatureEffect(item, &bearBite, DoBloodSplat);
2020-11-12 23:47:48 -06:00
LaraItem->hitPoints -= ATTACK_DAMAGE;
LaraItem->hitStatus = true;
2020-11-12 23:47:48 -06:00
item->requiredAnimState = BEAR_STOP;
}
break;
}
}
CreatureJoint(item, 0, head);
CreatureAnimation(itemNum, angle, 0);
2020-11-12 23:47:48 -06:00
}