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:
TokyoSU 2020-06-06 14:38:43 +02:00
parent 2c6a1a7480
commit 85e6941568
4 changed files with 178 additions and 149 deletions

View file

@ -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

View file

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

View file

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

View file

@ -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)
{