TombEngine/TR5Main/Objects/TR4/Entity/tr4_bat.cpp

200 lines
6.5 KiB
C++
Raw Normal View History

#include "framework.h"
#include "tr4_bat.h"
2021-09-19 23:41:26 +03:00
#include "control/box.h"
#include "control/control.h"
#include "effects\effects.h"
#include "misc.h"
#include "lara.h"
2021-09-19 23:41:26 +03:00
#include "control/lot.h"
#include "setup.h"
2021-09-08 18:31:35 +03:00
#include "Specific\trmath.h"
#include "itemdata/creature_info.h"
2021-08-29 14:20:05 +02:00
namespace TEN::Entities::TR4
{
2021-08-29 14:20:05 +02:00
enum BAT_STATE
{
STATE_BAT_EMPTY,
STATE_BAT_START,
STATE_BAT_FLY,
STATE_BAT_ATK,
STATE_BAT_FALLING,
STATE_BAT_DEATH,
STATE_BAT_IDLE
};
#define BAT_ANGLE ANGLE(20.0f)
2021-08-29 14:20:05 +02:00
constexpr auto BAT_ANIM_FALLING = 3;
constexpr auto BAT_ANIM_IDLE = 5;
constexpr auto BAT_ATTACK_RANGE = SQUARE(CLICK(1));
constexpr auto BAT_TARGETING_RANGE = SQUARE(SECTOR(5));
constexpr auto BAT_TARGET_YPOS = 896;
constexpr auto BAT_DAMAGE = 2;
static BITE_INFO batBite(0, 16, 45, 4);
static bool isBatCollideTarget(ITEM_INFO* item)
{
return item->touchBits >= 0;
}
2021-08-29 14:20:05 +02:00
void InitialiseBat(short itemNumber)
{
ITEM_INFO* item = &g_Level.Items[itemNumber];
2021-08-29 14:20:05 +02:00
InitialiseCreature(itemNumber);
2021-08-29 14:20:05 +02:00
item->animNumber = Objects[item->objectNumber].animIndex + BAT_ANIM_IDLE;
item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->goalAnimState = STATE_BAT_IDLE;
item->currentAnimState = STATE_BAT_IDLE;
}
2021-08-29 14:20:05 +02:00
void BatControl(short itemNumber)
{
if (!CreatureActive(itemNumber))
return;
2021-08-29 14:20:05 +02:00
ITEM_INFO* item, * target;
CREATURE_INFO* bat, * slots;
AI_INFO info;
int distance, bestdistance;
short angle;
2021-08-29 14:20:05 +02:00
item = &g_Level.Items[itemNumber];
bat = GetCreatureInfo(item);
angle = 0;
2021-08-29 14:20:05 +02:00
if (item->hitPoints > 0)
{
2021-08-29 14:20:05 +02:00
if (item->aiBits)
{
2021-08-29 14:20:05 +02:00
GetAITarget(bat);
}
else
{
bat->enemy = LaraItem;
2021-08-29 14:20:05 +02:00
// NOTE: it seems weird, bat could target any enemy including dogs for example
// check if voncroy are in range !
// take in account that the bat will always target voncroy if he exist and triggered !
// the bat will ignore lara completly !
/*bestdistance = MAXINT;
bat->enemy = LaraItem;
slots = &BaddieSlots[0];
for (int i = 0; i < NUM_SLOTS; i++, slots++)
{
if (slots->itemNum != NO_ITEM && slots->itemNum != itemNumber)
{
target = &g_Level.Items[slots->itemNum];
if (target->objectNumber == ID_VON_CROY)
{
int x, z;
x = target->pos.xPos - item->pos.xPos;
z = target->pos.zPos - item->pos.zPos;
distance = SQUARE(x) + SQUARE(z);
if (distance < bestdistance)
{
bat->enemy = target;
bestdistance = distance;
}
}
}
}*/
}
// NOTE: chaned from TIMID to VIOLENT, otherwise the bat seems to ignore Lara.
// Personally, i feel fine with bat always VIOLENT, but I will inspect also GetCreatureMood and CreatureMood functions
// for bugs.
CreatureAIInfo(item, &info);
GetCreatureMood(item, &info, VIOLENT);
if (bat->flags)
bat->mood = ESCAPE_MOOD;
CreatureMood(item, &info, VIOLENT);
angle = CreatureTurn(item, BAT_ANGLE);
switch (item->currentAnimState)
{
2021-08-29 14:20:05 +02:00
case STATE_BAT_IDLE:
if (info.distance < BAT_TARGETING_RANGE
|| item->hitStatus
|| bat->hurtByLara)
item->goalAnimState = STATE_BAT_START;
break;
case STATE_BAT_FLY:
if (info.distance < BAT_ATTACK_RANGE || !(GetRandomControl() & 0x3F))
bat->flags = 0;
if (!bat->flags)
{
if (item->touchBits
|| bat->enemy != LaraItem
&& info.distance < BAT_ATTACK_RANGE
&& info.ahead
&& abs(item->pos.yPos - bat->enemy->pos.yPos) < BAT_TARGET_YPOS)
{
item->goalAnimState = STATE_BAT_ATK;
}
}
break;
case STATE_BAT_ATK:
if (!bat->flags
&& (item->touchBits
|| bat->enemy != LaraItem)
&& info.distance < BAT_ATTACK_RANGE
2021-08-29 14:20:05 +02:00
&& info.ahead &&
abs(item->pos.yPos - bat->enemy->pos.yPos) < BAT_TARGET_YPOS)
{
2021-08-29 14:20:05 +02:00
CreatureEffect(item, &batBite, DoBloodSplat);
if (bat->enemy == LaraItem)
{
LaraItem->hitPoints -= BAT_DAMAGE;
LaraItem->hitStatus = true;
}
bat->flags = 1;
}
2021-08-29 14:20:05 +02:00
else
{
2021-08-29 14:20:05 +02:00
item->goalAnimState = STATE_BAT_FLY;
bat->mood = BORED_MOOD;
}
2021-08-29 14:20:05 +02:00
break;
}
}
2021-08-29 14:20:05 +02:00
else if (item->currentAnimState == STATE_BAT_ATK)
{
2021-08-29 14:20:05 +02:00
item->animNumber = Objects[item->objectNumber].animIndex + 1;
item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->goalAnimState = STATE_BAT_FLY;
item->currentAnimState = STATE_BAT_FLY;
}
else
{
2021-08-29 14:20:05 +02:00
if (item->pos.yPos >= item->floor)
{
item->goalAnimState = STATE_BAT_DEATH;
item->pos.yPos = item->floor;
item->gravityStatus = false;
}
else
{
item->gravityStatus = true;
item->animNumber = Objects[item->objectNumber].animIndex + BAT_ANIM_FALLING;
item->frameNumber = g_Level.Anims[item->animNumber].frameBase;
item->goalAnimState = STATE_BAT_FALLING;
item->currentAnimState = STATE_BAT_FALLING;
item->speed = 0;
}
}
2021-08-29 14:20:05 +02:00
CreatureAnimation(itemNumber, angle, 0);
}
Merge branch 'master' into item_data # Conflicts: # TR5Main/Game/Lara/lara.cpp # TR5Main/Game/Lara/lara_collide.cpp # TR5Main/Game/Lara/lara_monkey.cpp # TR5Main/Game/Lara/lara_struct.h # TR5Main/Game/Lara/lara_tests.cpp # TR5Main/Game/collide.h # TR5Main/Game/control.h # TR5Main/Game/effect.h # TR5Main/Game/effect2.cpp # TR5Main/Game/flipeffect.cpp # TR5Main/Game/floordata.h # TR5Main/Game/hair.cpp # TR5Main/Game/health.cpp # TR5Main/Game/items.cpp # TR5Main/Game/newinv2.cpp # TR5Main/Game/spotcam.cpp # TR5Main/Objects/Effects/tr4_bubbles.cpp # TR5Main/Objects/TR1/Entity/tr1_ape.cpp # TR5Main/Objects/TR1/Entity/tr1_bigrat.cpp # TR5Main/Objects/TR1/Entity/tr1_doppelganger.cpp # TR5Main/Objects/TR2/Entity/tr2_birdmonster.cpp # TR5Main/Objects/TR2/Entity/tr2_shark.cpp # TR5Main/Objects/TR2/Entity/tr2_spider.cpp # TR5Main/Objects/TR2/Entity/tr2_yeti.cpp # TR5Main/Objects/TR3/Entity/tr3_fishemitter.cpp # TR5Main/Objects/TR3/Entity/tr3_flamethrower.cpp # TR5Main/Objects/TR3/Entity/tr3_monkey.cpp # TR5Main/Objects/TR3/Entity/tr3_raptor.cpp # TR5Main/Objects/TR3/Entity/tr3_scuba.cpp # TR5Main/Objects/TR3/Entity/tr3_trex.cpp # TR5Main/Objects/TR3/Vehicles/kayak.cpp # TR5Main/Objects/TR3/Vehicles/minecart.cpp # TR5Main/Objects/TR4/Entity/tr4_bat.cpp # TR5Main/Objects/TR4/Entity/tr4_big_beetle.cpp # TR5Main/Objects/TR4/Entity/tr4_bigscorpion.cpp # TR5Main/Objects/TR4/Entity/tr4_demigod.cpp # TR5Main/Objects/TR4/Entity/tr4_dog.cpp # TR5Main/Objects/TR4/Entity/tr4_hammerhead.cpp # TR5Main/Objects/TR4/Entity/tr4_harpy.cpp # TR5Main/Objects/TR4/Entity/tr4_mutant.cpp # TR5Main/Objects/TR4/Entity/tr4_smallscorpion.cpp # TR5Main/Objects/TR4/Entity/tr4_troops.cpp # TR5Main/Objects/TR4/Entity/tr4_wildboar.cpp # TR5Main/Objects/TR4/Trap/tr4_joby_spikes.cpp # TR5Main/Objects/TR4/Vehicles/motorbike.cpp # TR5Main/Objects/TR5/Entity/tr5_doberman.cpp # TR5Main/Objects/TR5/Entity/tr5_imp.cpp # TR5Main/Objects/TR5/Entity/tr5_larson.cpp # TR5Main/Objects/TR5/Entity/tr5_lion.cpp # TR5Main/Objects/TR5/Entity/tr5_reaper.cpp # TR5Main/Objects/TR5/Object/tr5_pushableblock.cpp # TR5Main/Objects/TR5/Object/tr5_rollingball.cpp # TR5Main/Objects/TR5/Trap/tr5_fallingceiling.cpp # TR5Main/Renderer/Renderer11Draw2D.cpp # TR5Main/Specific/input.cpp # TR5Main/Specific/level.cpp # TR5Main/TombEngine.vcxproj.filters
2021-08-31 17:37:15 +02:00
}