From dc9c5837d085e171afaa43c9f0bd2c516b0856e4 Mon Sep 17 00:00:00 2001 From: XProger Date: Mon, 21 Jan 2019 00:27:15 +0300 Subject: [PATCH] add Winston AI; fix midas hand sparkles; --- src/cache.h | 1 + src/character.h | 14 ++++- src/enemy.h | 133 ++++++++++++++++++++++++++++++++++++++++++++++++ src/format.h | 7 ++- src/lara.h | 13 +---- src/level.h | 3 +- 6 files changed, 156 insertions(+), 15 deletions(-) diff --git a/src/cache.h b/src/cache.h index 1bc053c..b491208 100644 --- a/src/cache.h +++ b/src/cache.h @@ -83,6 +83,7 @@ struct ShaderCache { } void prepareShadows(int fx) { + compile(Core::passShadow, Shader::MIRROR, fx, rsShadow); compile(Core::passShadow, Shader::ENTITY, fx, rsShadow); compile(Core::passShadow, Shader::ENTITY, fx, rsShadow | RS_DISCARD); } diff --git a/src/character.h b/src/character.h index 77a6c34..c56b271 100644 --- a/src/character.h +++ b/src/character.h @@ -44,6 +44,7 @@ struct Character : Controller { vec3 velocity; float angleExt; float speed; + float lookAtSpeed; int stepHeight; int dropHeight; @@ -60,6 +61,8 @@ struct Character : Controller { stepHeight = 256; dropHeight = -256; + lookAtSpeed = 8.0f; + rangeChest = vec4(-0.80f, 0.80f, -0.75f, 0.75f) * PI; rangeHead = vec4(-0.25f, 0.25f, -0.50f, 0.50f) * PI; animation.initOverrides(); @@ -245,7 +248,7 @@ struct Character : Controller { void lookAtPos(const vec3 *t = NULL) { - float speed = 8.0f * Core::deltaTime; + float speed = lookAtSpeed * Core::deltaTime; quat rot; if (jointChest > -1) { @@ -304,6 +307,15 @@ struct Character : Controller { addBloodSpikes(); } + void bakeEnvironment(Texture *&environment) { + flags.invisible = true; + if (!environment) { + environment = new Texture(256, 256, FMT_RGBA, OPT_CUBEMAP | OPT_MIPMAPS | OPT_TARGET); + } + game->renderEnvironment(getRoomIndex(), pos - vec3(0.0f, 384.0f, 0.0f), &environment); + environment->generateMipMap(); + flags.invisible = false; + } }; #endif \ No newline at end of file diff --git a/src/enemy.h b/src/enemy.h index f499c3b..a37263e 100644 --- a/src/enemy.h +++ b/src/enemy.h @@ -3361,4 +3361,137 @@ struct Tiger : Enemy { } }; + +#define WINSTON_DIST 1536.0f +#define WINSTON_TURN_SLOW (DEG2RAD * 60) +#define WINSTON_FREEZE_TIME 60.0f + +struct Winston : Enemy { + + enum { + STATE_NONE , + STATE_STOP , + STATE_WALK , + }; + + Texture *environment; + + Winston(IGame *game, int entity) : Enemy(game, entity, 20, 341, 200.0f, 0.25f), environment(NULL) { + dropHeight = -1024; + jointChest = 11; + jointHead = 25; + nextState = STATE_NONE; + lookAtSpeed = 1.0f; + timer = 0.0f; + } + + virtual ~Winston() { + delete environment; + } + + virtual int getStateGround() { + if (getRoomIndex() == 94) { + int doorIndex = (level->version & TR::VER_TR2) ? 38 : 68; + + Controller *door = (Controller*)game->getLevel()->entities[doorIndex].controller; + if (!door->isActive()) { + if (timer > WINSTON_FREEZE_TIME) { + flags.unused |= 4; + if (!environment) { + bakeEnvironment(environment); + } + } else { + timer += Core::deltaTime; + } + return STATE_STOP; + } else { + if (!(flags.unused & 4)) { + timer = 0.0f; + } + } + } + + if (flags.unused & 4) { + timer -= Core::deltaTime; + if (timer < 0.0f) { + timer = 0.0f; + flags.unused &= ~4; + } + return STATE_STOP; + } + + if (!think(false)) + return state; + + if (nextState == state) + nextState = STATE_NONE; + + if (nextState != STATE_NONE) + return nextState; + + switch (state) { + case STATE_STOP : + if ((targetDist > WINSTON_DIST || !targetInView) && nextState != STATE_WALK) { + nextState = STATE_WALK; + game->playSound(TR::SND_WINSTON_WALK, pos, Sound::PAN); + } + case STATE_WALK : + if (targetDist < WINSTON_DIST) { + if (targetInView) { + nextState = STATE_STOP; + flags.unused &= ~1; + } else if (!(flags.unused & 1)) { + game->playSound(TR::SND_WINSTON_SCARED, pos, Sound::PAN); + game->playSound(TR::SND_WINSTON_TRAY, pos, Sound::PAN); + flags.unused |= 1; + } + } + } + + bool touch = collide(target) != 0; + bool push = (flags.unused & 2) != 0; + + if (!push && touch) { + game->playSound(TR::SND_WINSTON_PUSH, pos, Sound::PAN); + game->playSound(TR::SND_WINSTON_TRAY, pos, Sound::PAN); + flags.unused |= 2; + } + + if (push && !touch) { + flags.unused &= ~2; + } + + if (rand() < 0x100) { + game->playSound(TR::SND_WINSTON_TRAY, pos, Sound::PAN); + } + + return state; + } + + virtual void updatePosition() { + if (flags.unused & 4) { + animation.time = 0.0f; + animation.updateInfo(); + return; + } + + turn(state == STATE_WALK, WINSTON_TURN_SLOW); + angle.z = 0.0f; + + Enemy::updatePosition(); + setOverrides(true, jointChest, jointHead); + lookAt(target); + } + + virtual void render(Frustum *frustum, MeshBuilder *mesh, Shader::Type type, bool caustics) { + if (environment && (flags.unused & 4)) { + game->setRoomParams(getRoomIndex(), Shader::MIRROR, 1.5f, 2.0f, 2.5f, 1.0f, false); + environment->bind(sEnvironment); + Controller::render(frustum, mesh, type, caustics); + } else { + Enemy::render(frustum, mesh, type, caustics); + } + } +}; + #endif \ No newline at end of file diff --git a/src/format.h b/src/format.h index c6969dd..681a841 100644 --- a/src/format.h +++ b/src/format.h @@ -986,6 +986,11 @@ namespace TR { SND_SECRET = 173, SND_HELICOPTER = 297, + + SND_WINSTON_SCARED = 344, + SND_WINSTON_WALK = 345, + SND_WINSTON_PUSH = 346, + SND_WINSTON_TRAY = 347, }; enum { @@ -1902,7 +1907,7 @@ namespace TR { } bool castShadow() const { - return isLara() || isEnemy() || isVehicle() || isActor() || type == DART || type == TRAP_SWORD; + return isLara() || isEnemy() || isVehicle() || isActor() || type == DART || type == TRAP_SWORD || type == ENEMY_WINSTON || type == ENEMY_WINSTON_CAMO; } void getAxis(int &dx, int &dz) { diff --git a/src/lara.h b/src/lara.h index 65188bf..2a49881 100644 --- a/src/lara.h +++ b/src/lara.h @@ -1570,15 +1570,6 @@ struct Lara : Character { } } - void bakeEnvironment() { - flags.invisible = true; - if (!environment) - environment = new Texture(256, 256, FMT_RGBA, OPT_CUBEMAP | OPT_MIPMAPS | OPT_TARGET); - game->renderEnvironment(getRoomIndex(), pos - vec3(0.0f, 384.0f, 0.0f), &environment); - environment->generateMipMap(); - flags.invisible = false; - } - virtual void hit(float damage, Controller *enemy = NULL, TR::HitType hitType = TR::HIT_DEFAULT) { if (dozy || level->isCutsceneLevel()) return; @@ -1657,7 +1648,7 @@ struct Lara : Character { } case TR::HIT_MIDAS : { // generate environment map for reflections - bakeEnvironment(); + bakeEnvironment(environment); // set death animation animation.setAnim(level->models[TR::MODEL_LARA_SPEC].animation + 1); camera->doCutscene(pos, angle.y); @@ -3760,11 +3751,9 @@ struct Lara : Character { Core::updateLights(); */ environment->bind(sEnvironment); - Core::setBlendMode(bmAlpha); visibleMask ^= 0xFFFFFFFF; Controller::render(frustum, mesh, type, caustics); visibleMask ^= 0xFFFFFFFF; - Core::setBlendMode(bmNone); } } }; diff --git a/src/level.h b/src/level.h index bfbd4bb..01cb04b 100644 --- a/src/level.h +++ b/src/level.h @@ -1139,6 +1139,7 @@ struct Level : IGame { case TR::Entity::ENEMY_MERCENARY_SNOWMOBILE : case TR::Entity::ENEMY_MONK_1 : case TR::Entity::ENEMY_MONK_2 : return new Enemy(this, index, 100, 10, 0.0f, 0.0f); + case TR::Entity::ENEMY_WINSTON : return new Winston(this, index); case TR::Entity::CRYSTAL_PICKUP : return new CrystalPickup(this, index); case TR::Entity::STONE_ITEM_1 : @@ -1915,7 +1916,7 @@ struct Level : IGame { if (mesh->dynICount) { Core::lightPos[0] = vec4(0, 0, 0, 0); Core::lightColor[0] = vec4(0, 0, 0, 1); - setRoomParams(0, Shader::SPRITE, 1.0f, 1.0f, 0.0f, 1.0f, mesh->transparent == 1); + setRoomParams(getLara()->getRoomIndex(), Shader::SPRITE, 1.0f, 1.0f, 0.0f, 1.0f, mesh->transparent == 1); Basis b; b.w = 1.0f;