mirror of
https://github.com/TombEngine/TombEngine.git
synced 2025-04-30 16:57:57 +03:00

* Refactored gunflash. - Fixed rendering of gunflash. - Improved gen.bat with some comment. - Now entity can shoot with 2 weapon (left and right) like lara. * Fix compiling error * Move muzzleFlash to creature struct - Removed BiteInfo and remplaced it by CreatureBiteInfo. - Fixed Mafia2 and Cybord muzzleflash pos. - Added dynamic light and smoke when entity shoot. (only for weapon) * Able to switch GUN_FLASH mesh. * Improve CreatureEffect/Effect2 Pass bite directly instead. * Fixed TR5 and TR4 biteInfo * Finished implementing gunflash for creatures. - Fix snowmobile gun crash. - Fix knifethrower not throwing knife. * Removed traps cpp/h. * Update Changes.txt * Update Changes.txt * Update effects.cpp * Fixed build error * Update setup.cpp - Removed old ObjectObjects() and TrapObjects() and move the code to TR5 objects. * Fix mpgun gunflash not playing when dead. * Fixed snowmobile gun not appearing correctly - Fixed crash if ID_GUN_FLASH2 not exist and creature like snomobile driver shoot. - Fix the snowmobile driver AI that where commented (was disabled to test the gunflash). * Improved AssignObjectAnimations * Added new lot for snowmobile gun - Allow the snowmobile to drop from 4 block ! * Fixed savegame crash * Change what @Lwmte reviewed. * Added todo for snowmobile gun. - reverted NO_JOINT in CreatureBiteInfo causing error when compiling. * Fix compile error caused by the develop merge * Minor formatting * Update people.cpp --------- Co-authored-by: Sezz <sezzary@outlook.com> Co-authored-by: Kubsy <80340234+Kubsy@users.noreply.github.com>
248 lines
6.7 KiB
C++
248 lines
6.7 KiB
C++
#include "framework.h"
|
|
#include "Objects/TR1/Entity/tr1_wolf.h"
|
|
|
|
#include "Game/control/box.h"
|
|
#include "Game/control/control.h"
|
|
#include "Game/effects/effects.h"
|
|
#include "Game/items.h"
|
|
#include "Game/itemdata/creature_info.h"
|
|
#include "Game/Lara/lara.h"
|
|
#include "Game/misc.h"
|
|
#include "Math/Math.h"
|
|
#include "Specific/level.h"
|
|
#include "Specific/setup.h"
|
|
|
|
using namespace TEN::Math;
|
|
|
|
namespace TEN::Entities::Creatures::TR1
|
|
{
|
|
constexpr auto WOLF_BITE_DAMAGE = 100;
|
|
constexpr auto WOLF_LUNGE_DAMAGE = 50;
|
|
|
|
constexpr auto WOLF_ATTACK_RANGE = SQUARE(BLOCK(1.5f));
|
|
constexpr auto WOLF_STALK_RANGE = SQUARE(BLOCK(2));
|
|
|
|
constexpr auto WOLF_WAKE_CHANCE = 1.0f / 1024;
|
|
constexpr auto WOLF_SLEEP_CHANCE = 1.0f / 1024;
|
|
constexpr auto WOLF_HOWL_CHANCE = 1.0f / 85;
|
|
|
|
constexpr auto WOLF_SLEEP_FRAME = 96;
|
|
|
|
constexpr auto WOLF_WALK_TURN_RATE_MAX = ANGLE(2.0f);
|
|
constexpr auto WOLF_RUN_TURN_RATE_MAX = ANGLE(5.0f);
|
|
constexpr auto WOLF_STALK_TURN_RATE_MAX = ANGLE(2.0f);
|
|
|
|
const auto WolfBite = CreatureBiteInfo(Vector3i(0, -14, 174), 6);
|
|
const auto WolfAttackJoints = std::vector<unsigned int>{ 0, 1, 2, 3, 6, 8, 9, 10, 12, 13, 14 };
|
|
|
|
enum WolfState
|
|
{
|
|
// No state 0.
|
|
WOLF_STATE_IDLE = 1,
|
|
WOLF_STATE_WALK = 2,
|
|
WOLF_STATE_RUN = 3,
|
|
WOLF_STATE_JUMP = 4,
|
|
WOLF_STATE_STALK = 5,
|
|
WOLF_STATE_ATTACK = 6,
|
|
WOLF_STATE_HOWL = 7,
|
|
WOLF_STATE_SLEEP = 8,
|
|
WOLF_STATE_CROUCH = 9,
|
|
WOLF_STATE_FAST_TURN = 10,
|
|
WOLF_STATE_DEATH = 11,
|
|
WOLF_STATE_BITE = 12
|
|
};
|
|
|
|
// TODO
|
|
enum WolfAnim
|
|
{
|
|
WOLF_ANIM_DEATH = 20,
|
|
};
|
|
|
|
void InitializeWolf(short itemNumber)
|
|
{
|
|
auto* item = &g_Level.Items[itemNumber];
|
|
|
|
InitializeCreature(itemNumber);
|
|
item->Animation.FrameNumber = WOLF_SLEEP_FRAME;
|
|
}
|
|
|
|
void WolfControl(short itemNumber)
|
|
{
|
|
if (!CreatureActive(itemNumber))
|
|
return;
|
|
|
|
auto* item = &g_Level.Items[itemNumber];
|
|
auto* creature = GetCreatureInfo(item);
|
|
|
|
short angle = 0;
|
|
short tilt = 0;
|
|
short head = 0;
|
|
|
|
if (item->HitPoints <= 0)
|
|
{
|
|
if (item->Animation.ActiveState != WOLF_STATE_DEATH)
|
|
{
|
|
item->Animation.AnimNumber = Objects[ID_WOLF].animIndex + WOLF_ANIM_DEATH + (short)(GetRandomControl() / 11000);
|
|
item->Animation.FrameNumber = g_Level.Anims[item->Animation.AnimNumber].frameBase;
|
|
item->Animation.ActiveState = WOLF_STATE_DEATH;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
AI_INFO AI;
|
|
CreatureAIInfo(item, &AI);
|
|
|
|
if (AI.ahead)
|
|
head = AI.angle;
|
|
|
|
GetCreatureMood(item, &AI, false);
|
|
CreatureMood(item, &AI, false);
|
|
|
|
if (item->Animation.ActiveState != WOLF_STATE_SLEEP)
|
|
angle = CreatureTurn(item, creature->MaxTurn);
|
|
|
|
switch (item->Animation.ActiveState)
|
|
{
|
|
case WOLF_STATE_SLEEP:
|
|
head = 0;
|
|
|
|
if (creature->Mood == MoodType::Escape || AI.zoneNumber == AI.enemyZone)
|
|
{
|
|
item->Animation.RequiredState = WOLF_STATE_CROUCH;
|
|
item->Animation.TargetState = WOLF_STATE_IDLE;
|
|
}
|
|
else if (Random::TestProbability(WOLF_WAKE_CHANCE))
|
|
{
|
|
item->Animation.RequiredState = WOLF_STATE_WALK;
|
|
item->Animation.TargetState = WOLF_STATE_IDLE;
|
|
}
|
|
|
|
break;
|
|
|
|
case WOLF_STATE_IDLE:
|
|
if (item->Animation.RequiredState != NO_STATE)
|
|
item->Animation.TargetState = item->Animation.RequiredState;
|
|
else
|
|
item->Animation.TargetState = WOLF_STATE_WALK;
|
|
break;
|
|
|
|
case WOLF_STATE_WALK:
|
|
creature->MaxTurn = WOLF_WALK_TURN_RATE_MAX;
|
|
|
|
if (creature->Mood != MoodType::Bored)
|
|
{
|
|
item->Animation.TargetState = WOLF_STATE_STALK;
|
|
item->Animation.RequiredState = NO_STATE;
|
|
}
|
|
else if (Random::TestProbability(WOLF_SLEEP_CHANCE))
|
|
{
|
|
item->Animation.RequiredState = WOLF_STATE_SLEEP;
|
|
item->Animation.TargetState = WOLF_STATE_IDLE;
|
|
}
|
|
|
|
break;
|
|
|
|
case WOLF_STATE_CROUCH:
|
|
if (item->Animation.RequiredState != NO_STATE)
|
|
item->Animation.TargetState = item->Animation.RequiredState;
|
|
else if (creature->Mood == MoodType::Escape)
|
|
item->Animation.TargetState = WOLF_STATE_RUN;
|
|
else if (AI.distance < pow(345, 2) && AI.bite)
|
|
item->Animation.TargetState = WOLF_STATE_BITE;
|
|
else if (creature->Mood == MoodType::Stalk)
|
|
item->Animation.TargetState = WOLF_STATE_STALK;
|
|
else if (creature->Mood == MoodType::Bored)
|
|
item->Animation.TargetState = WOLF_STATE_IDLE;
|
|
else
|
|
item->Animation.TargetState = WOLF_STATE_RUN;
|
|
|
|
break;
|
|
|
|
case WOLF_STATE_STALK:
|
|
creature->MaxTurn = WOLF_STALK_TURN_RATE_MAX;
|
|
|
|
if (creature->Mood == MoodType::Escape)
|
|
item->Animation.TargetState = WOLF_STATE_RUN;
|
|
else if (AI.distance < pow(345, 2) && AI.bite)
|
|
item->Animation.TargetState = WOLF_STATE_BITE;
|
|
else if (AI.distance > pow(SECTOR(3), 2))
|
|
item->Animation.TargetState = WOLF_STATE_RUN;
|
|
else if (creature->Mood == MoodType::Attack)
|
|
{
|
|
if (!AI.ahead || AI.distance > pow(SECTOR(1.5f), 2) ||
|
|
(AI.enemyFacing < FRONT_ARC && AI.enemyFacing > -FRONT_ARC))
|
|
{
|
|
item->Animation.TargetState = WOLF_STATE_RUN;
|
|
}
|
|
}
|
|
else if (Random::TestProbability(WOLF_HOWL_CHANCE))
|
|
{
|
|
item->Animation.RequiredState = WOLF_STATE_HOWL;
|
|
item->Animation.TargetState = WOLF_STATE_CROUCH;
|
|
}
|
|
else if (creature->Mood == MoodType::Bored)
|
|
item->Animation.TargetState = WOLF_STATE_CROUCH;
|
|
|
|
break;
|
|
|
|
case WOLF_STATE_RUN:
|
|
creature->MaxTurn = WOLF_RUN_TURN_RATE_MAX;
|
|
tilt = angle;
|
|
|
|
if (AI.ahead && AI.distance < WOLF_ATTACK_RANGE)
|
|
{
|
|
if (AI.distance > (WOLF_ATTACK_RANGE / 2) &&
|
|
(AI.enemyFacing > FRONT_ARC || AI.enemyFacing < -FRONT_ARC))
|
|
{
|
|
item->Animation.RequiredState = WOLF_STATE_STALK;
|
|
item->Animation.TargetState = WOLF_STATE_CROUCH;
|
|
}
|
|
else
|
|
{
|
|
item->Animation.TargetState = WOLF_STATE_ATTACK;
|
|
item->Animation.RequiredState = NO_STATE;
|
|
}
|
|
}
|
|
else if (creature->Mood == MoodType::Stalk &&
|
|
AI.distance < WOLF_STALK_RANGE)
|
|
{
|
|
item->Animation.RequiredState = WOLF_STATE_STALK;
|
|
item->Animation.TargetState = WOLF_STATE_CROUCH;
|
|
}
|
|
else if (creature->Mood == MoodType::Bored)
|
|
item->Animation.TargetState = WOLF_STATE_CROUCH;
|
|
|
|
break;
|
|
|
|
case WOLF_STATE_ATTACK:
|
|
tilt = angle;
|
|
|
|
if (item->Animation.RequiredState == NO_STATE &&
|
|
item->TouchBits.Test(WolfAttackJoints))
|
|
{
|
|
item->Animation.RequiredState = WOLF_STATE_RUN;
|
|
DoDamage(creature->Enemy, WOLF_LUNGE_DAMAGE);
|
|
CreatureEffect(item, WolfBite, DoBloodSplat);
|
|
}
|
|
|
|
item->Animation.TargetState = WOLF_STATE_RUN;
|
|
break;
|
|
|
|
case WOLF_STATE_BITE:
|
|
if (AI.ahead && !item->Animation.RequiredState &&
|
|
item->TouchBits.Test(WolfAttackJoints))
|
|
{
|
|
item->Animation.RequiredState = WOLF_STATE_CROUCH;
|
|
DoDamage(creature->Enemy, WOLF_BITE_DAMAGE);
|
|
CreatureEffect(item, WolfBite, DoBloodSplat);
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
CreatureTilt(item, tilt);
|
|
CreatureJoint(item, 0, head);
|
|
CreatureAnimation(itemNumber, angle, tilt);
|
|
}
|
|
}
|