mirror of
https://github.com/XProger/OpenLara.git
synced 2025-08-06 13:16:52 +02:00
add Winston AI; fix midas hand sparkles;
This commit is contained in:
@@ -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);
|
||||||
}
|
}
|
||||||
|
@@ -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
|
133
src/enemy.h
133
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
|
#endif
|
@@ -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) {
|
||||||
|
13
src/lara.h
13
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) {
|
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@@ -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;
|
||||||
|
Reference in New Issue
Block a user