diff --git a/TR5Main/Game/Box.h b/TR5Main/Game/Box.h index cb65e7ea1..e95bb62f1 100644 --- a/TR5Main/Game/Box.h +++ b/TR5Main/Game/Box.h @@ -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 diff --git a/TR5Main/Game/draw.cpp b/TR5Main/Game/draw.cpp index 4bf8ccd9f..f0ca5ec63 100644 --- a/TR5Main/Game/draw.cpp +++ b/TR5Main/Game/draw.cpp @@ -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; diff --git a/TR5Main/Objects/TR4/Entity/tr4_bat.cpp b/TR5Main/Objects/TR4/Entity/tr4_bat.cpp index 0e73c0b2e..cfdfc4412 100644 --- a/TR5Main/Objects/TR4/Entity/tr4_bat.cpp +++ b/TR5Main/Objects/TR4/Entity/tr4_bat.cpp @@ -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); } \ No newline at end of file diff --git a/TR5Main/Objects/TR5/Entity/tr5_lion.cpp b/TR5Main/Objects/TR5/Entity/tr5_lion.cpp index 39aee9407..e42eff74c 100644 --- a/TR5Main/Objects/TR5/Entity/tr5_lion.cpp +++ b/TR5Main/Objects/TR5/Entity/tr5_lion.cpp @@ -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) {