From 80cd6d480b5b35a488e2fb4d8449cd2f1eada19d Mon Sep 17 00:00:00 2001 From: XProger Date: Tue, 26 Jun 2018 01:36:50 +0300 Subject: [PATCH] #14 cowboy AI --- src/enemy.h | 93 +++++++++++++++++++++++++++++++++++++-------------- src/format.h | 5 ++- src/trigger.h | 2 +- 3 files changed, 72 insertions(+), 28 deletions(-) diff --git a/src/enemy.h b/src/enemy.h index eaf74fe..b634449 100644 --- a/src/enemy.h +++ b/src/enemy.h @@ -226,7 +226,7 @@ struct Enemy : Character { animation.overrideMask &= ~(1 << chest); } - bool getTargetInfo(int height, vec3 *pos, float *angleX, float *angleY, float *dist) { + void getTargetInfo(int height, vec3 *pos, float *angleX, float *angleY, float *dist) { vec3 p = waypoint; p.y -= height; if (pos) *pos = p; @@ -240,7 +240,6 @@ struct Enemy : Character { if (angleX) *angleX = 0.0f; if (angleY) *angleY = atan2f(b.cross(a).dot(n), a.dot(b)); } - return true; } bool targetIsVisible(float maxDist) { @@ -307,7 +306,7 @@ struct Enemy : Character { void bite(int joint, const vec3 &offset, float damage) { ASSERT(target); target->hit(damage, this); - game->addEntity(TR::Entity::BLOOD, target->getRoomIndex(), getJoint(joint) * offset); + game->addEntity(TR::Entity::BLOOD, target->getRoomIndex(), target->getJoint(joint) * offset); } Mood getMoodFixed() { @@ -722,9 +721,6 @@ struct Lion : Enemy { if (!think(true)) return state; - float angle; - getTargetInfo(0, NULL, NULL, &angle, NULL); - if (nextState == state) nextState = STATE_NONE; @@ -1091,9 +1087,6 @@ struct Rat : Enemy { if (!think(false)) return state; - float angle; - getTargetInfo(0, NULL, NULL, &angle, NULL); - if (nextState == state) nextState = STATE_NONE; @@ -1134,9 +1127,6 @@ struct Rat : Enemy { if (!think(false)) return state; - float angle; - getTargetInfo(0, NULL, NULL, &angle, NULL); - if (nextState == state) nextState = STATE_NONE; @@ -1281,9 +1271,6 @@ struct Crocodile : Enemy { if (!think(true)) return state; - float angle; - getTargetInfo(0, NULL, NULL, &angle, NULL); - if (nextState == state) nextState = STATE_NONE; @@ -1333,9 +1320,6 @@ struct Crocodile : Enemy { if (!think(false)) return state; - float angle; - getTargetInfo(0, NULL, NULL, &angle, NULL); - if (nextState == state) nextState = STATE_NONE; @@ -2498,7 +2482,7 @@ struct Human : Enemy { STATE_RUN, STATE_AIM, STATE_DEATH, - STATE_WAIT, // == STATE_FIRE for MrT + STATE_WAIT, // == STATE_FIRE for MrT and Cowboy STATE_FIRE }; @@ -2573,9 +2557,6 @@ struct Larson : Human { if (!think(false)) return state; - float angle; - getTargetInfo(0, NULL, NULL, &angle, NULL); - if (nextState == state) nextState = STATE_NONE; @@ -2667,6 +2648,9 @@ struct SkaterBoy : Human { }; +#define COWBOY_DIST_WALK (3 * 1024) +#define COWBOY_DAMAGE 70 + struct Cowboy : Human { Cowboy(IGame *game, int entity) : Human(game, entity, 150) { @@ -2676,10 +2660,70 @@ struct Cowboy : Human { virtual void onDead() { game->addEntity(TR::Entity::MAGNUMS, getRoomIndex(), pos, 0); } + + virtual int getStateGround() { + if (!think(false)) + return state; + + if (nextState == state) + nextState = STATE_NONE; + + switch (state) { + // same as Mr. T + case STATE_STOP : + if (nextState != STATE_NONE) + return nextState; + if (targetIsVisible(HUMAN_DIST_SHOT)) + return STATE_AIM; + if (mood == MOOD_SLEEP) + return STATE_WALK; + return STATE_RUN; + case STATE_WALK : + if (mood == MOOD_ESCAPE || !targetInView) + nextState = STATE_RUN; + else if (targetIsVisible(HUMAN_DIST_SHOT)) + nextState = STATE_AIM; + else if (targetDist > COWBOY_DIST_WALK) + nextState = STATE_RUN; + else + break; + return STATE_STOP; + case STATE_RUN : + if (mood == MOOD_ESCAPE || !targetInView) + break; + if (targetIsVisible(HUMAN_DIST_SHOT)) + nextState = STATE_AIM; + else if (targetDist < COWBOY_DIST_WALK && targetInView) + nextState = STATE_WALK; + else + break; + return STATE_STOP; + case STATE_AIM : + flags.unused = 7; + if (nextState != STATE_NONE) + return STATE_STOP; + if (targetIsVisible(HUMAN_DIST_SHOT)) + return STATE_WAIT; // STATE_FIRE + return STATE_STOP; + // ---- + case STATE_WAIT : // STATE_FIRE + if (animation.frameIndex != flags.unused && (animation.frameIndex == 0 || animation.frameIndex == 4)) { + jointGun = (flags.unused == 7) ? 8 : 5; + doShot(COWBOY_DAMAGE, vec3(0, -40, 40)); + flags.unused = animation.frameIndex; + } + + if (mood == MOOD_ESCAPE) + nextState = STATE_RUN; + break; + } + + return state; + } }; -#define MRT_DIST_WALK 4096 +#define MRT_DIST_WALK (4 * 1024) #define MRT_DAMAGE 150 struct MrT : Human { @@ -2700,9 +2744,6 @@ struct MrT : Human { if (!think(false)) return state; - float angle; - getTargetInfo(0, NULL, NULL, &angle, NULL); - if (nextState == state) nextState = STATE_NONE; diff --git a/src/format.h b/src/format.h index b7c55ca..3f933d8 100644 --- a/src/format.h +++ b/src/format.h @@ -1378,7 +1378,7 @@ namespace TR { return sectors + sx * zSectors + sz; } - void addDynLight(int32 id, const vec4 &pos, const vec4 &color) { + void addDynLight(int32 id, const vec4 &pos, const vec4 &color, bool priority = false) { DynLight *light = NULL; for (int i = 0; i < dynLightsCount; i++) if (dynLights[i].id == id) { @@ -1399,6 +1399,9 @@ namespace TR { light->id = id; light->pos = pos; light->color = color; + + if (priority && dynLights[0].id != id) + swap(dynLights[0], dynLights[1]); } void removeDynLight(int32 id) { diff --git a/src/trigger.h b/src/trigger.h index 5a066f2..a3f9e9f 100644 --- a/src/trigger.h +++ b/src/trigger.h @@ -232,7 +232,7 @@ struct MuzzleFlash : Controller { Core::lightPos[lightIndex] = lightPos; Core::lightColor[lightIndex] = lightColor; } else - getRoom().addDynLight(owner->entity, lightPos, lightColor); + getRoom().addDynLight(owner->entity, lightPos, lightColor, true); } else { if (lightIndex > -1) { ASSERT(lightIndex < MAX_LIGHTS);