1
0
mirror of https://github.com/XProger/OpenLara.git synced 2025-08-06 05:07:48 +02:00

add Winston AI; fix midas hand sparkles;

This commit is contained in:
XProger
2019-01-21 00:27:15 +03:00
parent b93cf4b71d
commit dc9c5837d0
6 changed files with 156 additions and 15 deletions

View File

@@ -83,6 +83,7 @@ struct ShaderCache {
} }
void prepareShadows(int fx) { 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);
compile(Core::passShadow, Shader::ENTITY, fx, rsShadow | RS_DISCARD); compile(Core::passShadow, Shader::ENTITY, fx, rsShadow | RS_DISCARD);
} }

View File

@@ -44,6 +44,7 @@ struct Character : Controller {
vec3 velocity; vec3 velocity;
float angleExt; float angleExt;
float speed; float speed;
float lookAtSpeed;
int stepHeight; int stepHeight;
int dropHeight; int dropHeight;
@@ -60,6 +61,8 @@ struct Character : Controller {
stepHeight = 256; stepHeight = 256;
dropHeight = -256; dropHeight = -256;
lookAtSpeed = 8.0f;
rangeChest = vec4(-0.80f, 0.80f, -0.75f, 0.75f) * PI; rangeChest = vec4(-0.80f, 0.80f, -0.75f, 0.75f) * PI;
rangeHead = vec4(-0.25f, 0.25f, -0.50f, 0.50f) * PI; rangeHead = vec4(-0.25f, 0.25f, -0.50f, 0.50f) * PI;
animation.initOverrides(); animation.initOverrides();
@@ -245,7 +248,7 @@ struct Character : Controller {
void lookAtPos(const vec3 *t = NULL) { void lookAtPos(const vec3 *t = NULL) {
float speed = 8.0f * Core::deltaTime; float speed = lookAtSpeed * Core::deltaTime;
quat rot; quat rot;
if (jointChest > -1) { if (jointChest > -1) {
@@ -304,6 +307,15 @@ struct Character : Controller {
addBloodSpikes(); 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 #endif

View File

@@ -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 #endif

View File

@@ -986,6 +986,11 @@ namespace TR {
SND_SECRET = 173, SND_SECRET = 173,
SND_HELICOPTER = 297, SND_HELICOPTER = 297,
SND_WINSTON_SCARED = 344,
SND_WINSTON_WALK = 345,
SND_WINSTON_PUSH = 346,
SND_WINSTON_TRAY = 347,
}; };
enum { enum {
@@ -1902,7 +1907,7 @@ namespace TR {
} }
bool castShadow() const { 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) { void getAxis(int &dx, int &dz) {

View File

@@ -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) { virtual void hit(float damage, Controller *enemy = NULL, TR::HitType hitType = TR::HIT_DEFAULT) {
if (dozy || level->isCutsceneLevel()) return; if (dozy || level->isCutsceneLevel()) return;
@@ -1657,7 +1648,7 @@ struct Lara : Character {
} }
case TR::HIT_MIDAS : { case TR::HIT_MIDAS : {
// generate environment map for reflections // generate environment map for reflections
bakeEnvironment(); bakeEnvironment(environment);
// set death animation // set death animation
animation.setAnim(level->models[TR::MODEL_LARA_SPEC].animation + 1); animation.setAnim(level->models[TR::MODEL_LARA_SPEC].animation + 1);
camera->doCutscene(pos, angle.y); camera->doCutscene(pos, angle.y);
@@ -3760,11 +3751,9 @@ struct Lara : Character {
Core::updateLights(); Core::updateLights();
*/ */
environment->bind(sEnvironment); environment->bind(sEnvironment);
Core::setBlendMode(bmAlpha);
visibleMask ^= 0xFFFFFFFF; visibleMask ^= 0xFFFFFFFF;
Controller::render(frustum, mesh, type, caustics); Controller::render(frustum, mesh, type, caustics);
visibleMask ^= 0xFFFFFFFF; visibleMask ^= 0xFFFFFFFF;
Core::setBlendMode(bmNone);
} }
} }
}; };

View File

@@ -1139,6 +1139,7 @@ struct Level : IGame {
case TR::Entity::ENEMY_MERCENARY_SNOWMOBILE : case TR::Entity::ENEMY_MERCENARY_SNOWMOBILE :
case TR::Entity::ENEMY_MONK_1 : 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_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::CRYSTAL_PICKUP : return new CrystalPickup(this, index);
case TR::Entity::STONE_ITEM_1 : case TR::Entity::STONE_ITEM_1 :
@@ -1915,7 +1916,7 @@ struct Level : IGame {
if (mesh->dynICount) { if (mesh->dynICount) {
Core::lightPos[0] = vec4(0, 0, 0, 0); Core::lightPos[0] = vec4(0, 0, 0, 0);
Core::lightColor[0] = vec4(0, 0, 0, 1); 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; Basis b;
b.w = 1.0f; b.w = 1.0f;