1
0
mirror of https://github.com/XProger/OpenLara.git synced 2025-04-22 03:51:58 +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) {
compile(Core::passShadow, Shader::MIRROR, fx, rsShadow);
compile(Core::passShadow, Shader::ENTITY, fx, rsShadow);
compile(Core::passShadow, Shader::ENTITY, fx, rsShadow | RS_DISCARD);
}

View File

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

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

View File

@ -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) {

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) {
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);
}
}
};

View File

@ -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;