From 72cc69e7562e910440c5185a9984c4b47412b7c7 Mon Sep 17 00:00:00 2001 From: XProger Date: Tue, 27 Feb 2018 06:34:36 +0300 Subject: [PATCH] #14 AI for lions (male, female) and puma --- src/enemy.h | 123 +++++++++++++++++++++++++++++++++++++++++++++++++++- src/level.h | 2 +- 2 files changed, 122 insertions(+), 3 deletions(-) diff --git a/src/enemy.h b/src/enemy.h index 54006e1..e6b8347 100644 --- a/src/enemy.h +++ b/src/enemy.h @@ -462,7 +462,6 @@ struct Enemy : Character { #define WOLF_TURN_FAST (DEG2RAD * 150) #define WOLF_TURN_SLOW (DEG2RAD * 60) - #define WOLF_DIST_STALK STALK_BOX #define WOLF_DIST_BITE 345 #define WOLF_DIST_ATTACK (1024 + 512) @@ -619,9 +618,129 @@ struct Wolf : Enemy { } }; + +#define LION_DIST_ATTACK 1024 +#define LION_TURN_FAST (DEG2RAD * 150) +#define LION_TURN_SLOW (DEG2RAD * 60) + struct Lion : Enemy { + + enum { + HIT_MASK = 0x380066, + }; + + enum { + ANIM_DEATH_LION = 7, + ANIM_DEATH_PUMA = 4, + }; + + enum { + STATE_NONE , + STATE_STOP , + STATE_WALK , + STATE_RUN , + STATE_ATTACK , + STATE_DEATH , + STATE_ROAR , + STATE_BITE , + }; + Lion(IGame *game, int entity) : Enemy(game, entity, 6, 341, 375.0f, 0.25f) { - hitSound = TR::SND_HIT_LION; + dropHeight = -1024; + jointChest = 19; + jointHead = 20; + switch (getEntity().type) { + case TR::Entity::ENEMY_LION_MALE : + hitSound = TR::SND_HIT_LION; + health = 30.0f; + aggression = 1.0f; + break; + case TR::Entity::ENEMY_LION_FEMALE : + hitSound = TR::SND_HIT_LION; + health = 25.0f; + break; + case TR::Entity::ENEMY_PUMA : + health = 45.0f; + break; + default : ; + } + } + + virtual int getStateGround() { + if (!think(false)) + return state; + + float angle; + getTargetInfo(0, NULL, NULL, &angle, NULL); + + bool inZone = target ? target->zone == zone : false; + + if (nextState == state) + nextState = STATE_NONE; + + switch (state) { + case STATE_STOP : + if (nextState != STATE_NONE) + return nextState; + if (mood == MOOD_SLEEP) + return STATE_WALK; + if (targetInView && (collide(target) & HIT_MASK)) + return STATE_BITE; + if (targetInView && targetDist < LION_DIST_ATTACK) + return STATE_ATTACK; + return STATE_RUN; + case STATE_WALK : + if (mood != MOOD_SLEEP) + return STATE_STOP; + if (randf() < 0.0004f) { + nextState = STATE_ROAR; + return STATE_STOP; + } + break; + case STATE_RUN : + if ((mood == MOOD_SLEEP) || + (targetInView && targetDist < LION_DIST_ATTACK) || + (targetInView && (collide(target) & HIT_MASK))) + return STATE_STOP; + if (mood == MOOD_ESCAPE && randf() < 0.0004f) { + nextState = STATE_ROAR; + return STATE_STOP; + } + break; + case STATE_ATTACK : + case STATE_BITE : + if (nextState == STATE_NONE && (collide(target) & HIT_MASK)) { + bite(getJoint(jointHead).pos, state == STATE_ATTACK ? 150.0f : 250.0f); + nextState = STATE_STOP; + } + } + + return state; + } + + virtual int getStateDeath() { + if (state == STATE_DEATH) + return state; + int deathAnim = (getEntity().type == TR::Entity::ENEMY_PUMA) ? ANIM_DEATH_PUMA : ANIM_DEATH_LION; + return animation.setAnim(deathAnim + rand() % 2); + } + + virtual void updatePosition() { + float angleY = 0.0f; + + if (state == STATE_RUN || state == STATE_WALK || state == STATE_ROAR) + getTargetInfo(0, NULL, NULL, &angleY, NULL); + + turn(angleY, state == STATE_RUN ? LION_TURN_FAST : LION_TURN_SLOW); + + if (state == STATE_DEATH) { + animation.overrideMask = 0; + return; + } + + Enemy::updatePosition(); + setOverrides(state != STATE_DEATH, jointChest, jointHead); + lookAt(target); } }; diff --git a/src/level.h b/src/level.h index 7394214..4bb5456 100644 --- a/src/level.h +++ b/src/level.h @@ -703,6 +703,7 @@ struct Level : IGame { case TR::Entity::ENEMY_WOLF : return new Wolf(this, index); case TR::Entity::ENEMY_BEAR : return new Bear(this, index); case TR::Entity::ENEMY_BAT : return new Bat(this, index); + case TR::Entity::ENEMY_PUMA : case TR::Entity::ENEMY_LION_MALE : case TR::Entity::ENEMY_LION_FEMALE : return new Lion(this, index); case TR::Entity::ENEMY_RAT_LAND : @@ -716,7 +717,6 @@ struct Level : IGame { case TR::Entity::ENEMY_MUMMY : return new Mummy(this, index); case TR::Entity::ENEMY_CROCODILE_LAND : case TR::Entity::ENEMY_CROCODILE_WATER : - case TR::Entity::ENEMY_PUMA : case TR::Entity::ENEMY_GORILLA : return new Enemy(this, index, 100, 10, 0.0f, 0.0f); case TR::Entity::ENEMY_LARSON : return new Larson(this, index); case TR::Entity::ENEMY_PIERRE : return new Pierre(this, index);