mirror of
https://github.com/TombEngine/TombEngine.git
synced 2025-05-06 19:01:06 +03:00
Refactored Bat
- Latest bat code from TR4Main. - Fixed Semi-Always Not Attacking Lara (Collision). - Fixed Escape Mood (Bat can fly without attacking lara and can be killed easy like this !)
This commit is contained in:
parent
2c6a1a7480
commit
85e6941568
4 changed files with 178 additions and 149 deletions
|
@ -72,6 +72,22 @@ typedef struct BITE_INFO
|
|||
int y;
|
||||
int z;
|
||||
int meshNum;
|
||||
|
||||
BITE_INFO()
|
||||
{
|
||||
this->x = 0;
|
||||
this->y = 0;
|
||||
this->z = 0;
|
||||
this->meshNum = 0;
|
||||
}
|
||||
|
||||
BITE_INFO(int xpos, int ypos, int zpos, int meshNumber)
|
||||
{
|
||||
this->x = xpos;
|
||||
this->y = ypos;
|
||||
this->z = zpos;
|
||||
this->meshNum = meshNumber;
|
||||
}
|
||||
};
|
||||
|
||||
typedef struct LOT_INFO
|
||||
|
|
|
@ -7,15 +7,15 @@
|
|||
|
||||
BITE_INFO EnemyBites[9] =
|
||||
{
|
||||
{ 0x14, 0xFFFFFFA1, 0xF0, 0xD },
|
||||
{ 0x30, 0, 0xB4, 0xFFFFFFF5 },
|
||||
{ 0xFFFFFFD0, 0, 0xB4, 0xE },
|
||||
{ 0xFFFFFFC9, 5, 0xE1, 0xE },
|
||||
{ 0xF, 0xFFFFFFC4, 0xC3, 0xD },
|
||||
{ 0xFFFFFFE2, 0xFFFFFFBF, 0xFA, 0x12 },
|
||||
{ 0, 0xFFFFFF92, 0x1E0, 0xD },
|
||||
{ 0xFFFFFFEC, 0xFFFFFFB0, 0xBE, 0xFFFFFFF6 },
|
||||
{ 0xA, 0xFFFFFFC4, 0xC8, 0xD }
|
||||
{ 20, -95, 240, 13 },
|
||||
{ 48, 0, 180, -11 },
|
||||
{ -48, 0, 180, 14 },
|
||||
{ -48, 5, 225, 14 },
|
||||
{ 15, -60, 195, 13 },
|
||||
{ -30, -65, 250, 18 },
|
||||
{ 0, -110, 480, 13 },
|
||||
{ -20, -80, 190, -10 },
|
||||
{ 10, -60, 200, 13 }
|
||||
};
|
||||
|
||||
int LightningCount;
|
||||
|
|
|
@ -1,25 +1,56 @@
|
|||
#include "framework.h"
|
||||
#include "tr4_bat.h"
|
||||
#include "box.h"
|
||||
#include "effect.h"
|
||||
#include "items.h"
|
||||
#include "setup.h"
|
||||
#include "lot.h"
|
||||
#include "level.h"
|
||||
#include "control.h"
|
||||
#include "effect2.h"
|
||||
#include "misc.h"
|
||||
#include "lara.h"
|
||||
#include "lot.h"
|
||||
#include "setup.h"
|
||||
#include "trmath.h"
|
||||
|
||||
BITE_INFO batBite = { 0, 16, 45, 4 };
|
||||
|
||||
enum BAT_STATE
|
||||
{
|
||||
BAT_EMPTY,
|
||||
BAT_START,
|
||||
BAT_FLY,
|
||||
BAT_ATK,
|
||||
BAT_FALLING,
|
||||
BAT_DEATH,
|
||||
BAT_IDLE
|
||||
};
|
||||
|
||||
enum BAT_ANIM
|
||||
{
|
||||
ANIM_BAT_START,
|
||||
ANIM_BAT_FLY,
|
||||
ANIM_BAT_ATK,
|
||||
ANIM_BAT_FALLING,
|
||||
ANIM_BAT_HIT_FLOOR,
|
||||
ANIM_BAT_IDLE
|
||||
};
|
||||
|
||||
#define BAT_ANGLE ANGLE(20.0f)
|
||||
constexpr auto BAT_ATTACK_RANGE = SQUARE(CLICK(1));
|
||||
constexpr auto BAT_TARGETING_RANGE = SQUARE(SECTOR(5));
|
||||
constexpr auto BAT_TARGET_YPOS = SQUARE(CLICK(2) / 18);
|
||||
constexpr auto BAT_DAMAGE = 2;
|
||||
static BITE_INFO batBite(0, 16, 45, 4);
|
||||
|
||||
static bool isBatCollideTarget(ITEM_INFO* item)
|
||||
{
|
||||
return item->touchBits >= 0;
|
||||
}
|
||||
|
||||
void InitialiseBat(short itemNumber)
|
||||
{
|
||||
ITEM_INFO* item = &Items[itemNumber];
|
||||
|
||||
ClearItem(itemNumber);
|
||||
|
||||
item->animNumber = Objects[ID_BAT].animIndex + 5;
|
||||
InitialiseCreature(itemNumber);
|
||||
item->animNumber = Objects[item->objectNumber].animIndex + ANIM_BAT_IDLE;
|
||||
item->frameNumber = Anims[item->animNumber].frameBase;
|
||||
item->goalAnimState = 6;
|
||||
item->currentAnimState = 6;
|
||||
item->goalAnimState = BAT_IDLE;
|
||||
item->currentAnimState = BAT_IDLE;
|
||||
}
|
||||
|
||||
void BatControl(short itemNumber)
|
||||
|
@ -27,137 +58,119 @@ void BatControl(short itemNumber)
|
|||
if (!CreatureActive(itemNumber))
|
||||
return;
|
||||
|
||||
ITEM_INFO* item = &Items[itemNumber];
|
||||
CREATURE_INFO* creature = (CREATURE_INFO*)item->data;
|
||||
short angle = 0;
|
||||
short head = 0;
|
||||
short neck = 0;
|
||||
short tilt = 0;
|
||||
short joint0 = 0;
|
||||
short joint1 = 0;
|
||||
short joint2 = 0;
|
||||
short joint3 = 0;
|
||||
ITEM_INFO* item, *target;
|
||||
CREATURE_INFO* bat, *slots;
|
||||
AI_INFO info;
|
||||
int distance, bestdistance;
|
||||
short angle;
|
||||
|
||||
if (item->hitPoints > 0)
|
||||
{
|
||||
int dx = LaraItem->pos.xPos - item->pos.xPos;
|
||||
int dz = LaraItem->pos.zPos - item->pos.zPos;
|
||||
int laraDistance = dx * dx + dz * dz;
|
||||
item = &Items[itemNumber];
|
||||
bat = GetCreatureInfo(item);
|
||||
angle = 0;
|
||||
|
||||
if (item->aiBits)
|
||||
{
|
||||
GetAITarget(creature);
|
||||
}
|
||||
else
|
||||
{
|
||||
creature->enemy = LaraItem;
|
||||
if (item->hitPoints <= 0)
|
||||
{
|
||||
if (item->pos.yPos >= item->floor)
|
||||
{
|
||||
item->goalAnimState = BAT_DEATH;
|
||||
item->pos.yPos = item->floor;
|
||||
item->gravityStatus = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
item->animNumber = Objects[item->objectNumber].animIndex + ANIM_BAT_FALLING;
|
||||
item->frameNumber = Anims[item->animNumber].frameBase;
|
||||
item->goalAnimState = BAT_FALLING;
|
||||
item->currentAnimState = BAT_FALLING;
|
||||
item->speed = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (item->aiBits & ALL_AIOBJ)
|
||||
{
|
||||
GetAITarget(bat);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 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;
|
||||
|
||||
CREATURE_INFO* baddie = &BaddieSlots[0];
|
||||
CREATURE_INFO* found = &BaddieSlots[0];
|
||||
int minDistance = 0x7FFFFFFF;
|
||||
slots = &BaddieSlots[0];
|
||||
for (int i = 0; i < NUM_SLOTS; i++, slots++)
|
||||
{
|
||||
target = &Items[slots->itemNum];
|
||||
if (target->objectNumber == ID_VON_CROY && target->status != ITEM_INVISIBLE)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < NUM_SLOTS; i++, baddie++)
|
||||
{
|
||||
if (baddie->itemNum == NO_ITEM || baddie->itemNum == itemNumber)
|
||||
continue;
|
||||
CreatureAIInfo(item, &info);
|
||||
GetCreatureMood(item, &info, TIMID);
|
||||
// note: this random dont exist in TR4 !
|
||||
// this part set the bat in escape mood, but for too long !
|
||||
// lara can escape and shot it easy ....
|
||||
if (bat->flags && !(GetRandomControl() & 16))
|
||||
bat->mood = ESCAPE_MOOD;
|
||||
else if (bat->flags && GetRandomControl() & 24) // fine maybe ? the bat react more with "16" but this reaction is too fast !
|
||||
bat->mood = STALK_MOOD;
|
||||
CreatureMood(item, &info, TIMID);
|
||||
angle = CreatureTurn(item, BAT_ANGLE);
|
||||
|
||||
ITEM_INFO* target = &Items[baddie->itemNum];
|
||||
if (target->objectNumber != ID_WILD_BOAR)
|
||||
{
|
||||
int dx2 = target->pos.xPos - item->pos.xPos;
|
||||
int dz2 = target->pos.zPos - item->pos.zPos;
|
||||
int distance = dx2 * dx2 + dz2 * dz2;
|
||||
switch (item->currentAnimState)
|
||||
{
|
||||
case BAT_IDLE:
|
||||
if (info.distance < BAT_TARGETING_RANGE || item->hitStatus || bat->hurtByLara)
|
||||
item->goalAnimState = BAT_START;
|
||||
break;
|
||||
case BAT_FLY:
|
||||
if (info.distance < BAT_ATTACK_RANGE || !(GetRandomControl() & 0x3F))
|
||||
bat->flags = 0;
|
||||
|
||||
if (distance < minDistance)
|
||||
{
|
||||
creature->enemy = target;
|
||||
minDistance = distance;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!bat->flags)
|
||||
{
|
||||
if (isBatCollideTarget(item) || bat->enemy != LaraItem)
|
||||
{
|
||||
if (info.distance < BAT_ATTACK_RANGE
|
||||
&& info.ahead && abs(item->pos.yPos - bat->enemy->pos.yPos) < BAT_TARGET_YPOS)
|
||||
{
|
||||
item->goalAnimState = BAT_ATK;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case BAT_ATK:
|
||||
if (!bat->flags && (isBatCollideTarget(item) || bat->enemy != LaraItem) && info.distance < BAT_ATTACK_RANGE && info.ahead && abs(item->pos.yPos - bat->enemy->pos.yPos) < BAT_TARGET_YPOS)
|
||||
{
|
||||
CreatureEffect(item, &batBite, DoBloodSplat);
|
||||
if (bat->enemy == LaraItem)
|
||||
{
|
||||
LaraItem->hitPoints -= BAT_DAMAGE;
|
||||
LaraItem->hitStatus = TRUE;
|
||||
}
|
||||
bat->flags = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
item->goalAnimState = BAT_FLY;
|
||||
bat->mood = BORED_MOOD;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
AI_INFO info;
|
||||
CreatureAIInfo(item, &info);
|
||||
|
||||
GetCreatureMood(item, &info, TIMID);
|
||||
//if (item->flags)
|
||||
// creature->mood = ESCAPE_MOOD;
|
||||
CreatureMood(item, &info, TIMID);
|
||||
|
||||
angle = CreatureTurn(item, ANGLE(20));
|
||||
|
||||
switch (item->currentAnimState)
|
||||
{
|
||||
case 2:
|
||||
if (info.distance < SQUARE(256) || !(GetRandomControl() & 0x3F))
|
||||
{
|
||||
creature->flags = 0;
|
||||
}
|
||||
|
||||
if (!creature->flags)
|
||||
{
|
||||
if (item->touchBits || creature->enemy != LaraItem && info.distance < SQUARE(256) && info.ahead && abs(item->pos.yPos - creature->enemy->pos.yPos) < 896)
|
||||
{
|
||||
item->goalAnimState = 3;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 3:
|
||||
if (!creature->flags && (item->touchBits || creature->enemy != LaraItem && info.distance < SQUARE(256) && info.ahead && abs(item->pos.yPos - creature->enemy->pos.yPos) < 896))
|
||||
{
|
||||
CreatureEffect(item, &batBite, DoBloodSplat);
|
||||
if (creature->enemy == LaraItem)
|
||||
{
|
||||
LaraItem->hitPoints -= 2;
|
||||
LaraItem->hitStatus = true;
|
||||
}
|
||||
creature->flags = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
item->goalAnimState = 2;
|
||||
creature->mood = BORED_MOOD;
|
||||
}
|
||||
break;
|
||||
|
||||
case 6:
|
||||
if (info.distance < SQUARE(5120) ||
|
||||
item->hitStatus ||
|
||||
creature->hurtByLara)
|
||||
{
|
||||
item->goalAnimState = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
else if (item->currentAnimState == 3)
|
||||
{
|
||||
item->animNumber = Objects[ID_BAT].animIndex + 1;
|
||||
item->frameNumber = Anims[item->animNumber].frameBase;
|
||||
item->goalAnimState = 2;
|
||||
item->currentAnimState = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (item->pos.yPos >= item->floor)
|
||||
{
|
||||
item->goalAnimState = 5;
|
||||
item->pos.yPos = item->floor;
|
||||
item->gravityStatus = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
item->gravityStatus = true;
|
||||
item->animNumber = Objects[ID_BAT].animIndex + 3;
|
||||
item->frameNumber = Anims[item->animNumber].frameBase;
|
||||
item->goalAnimState = 4;
|
||||
item->currentAnimState = 4;
|
||||
item->speed = 0;
|
||||
}
|
||||
}
|
||||
|
||||
CreatureAnimation(itemNumber, angle, 0);
|
||||
CreatureAnimation(itemNumber, angle, 0);
|
||||
}
|
|
@ -11,8 +11,8 @@
|
|||
#include "level.h"
|
||||
#include "lara.h"
|
||||
|
||||
BITE_INFO LionBite1 = { 0xFFFFFFFE, 0xFFFFFFF6, 0xFA, 0x15 };
|
||||
BITE_INFO LionBite2 = { 0xFFFFFFFE, 0xFFFFFFF6, 0x84, 0x15 };
|
||||
BITE_INFO LionBite1 = { -2, -10, 250, 21 };
|
||||
BITE_INFO LionBite2 = { -2, -10, 132, 21 };
|
||||
|
||||
void InitialiseLion(short itemNum)
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue