From 7d43b2426c8ae6b0a105b2b053a3a90dce301f5d Mon Sep 17 00:00:00 2001 From: XProger Date: Fri, 13 Oct 2017 10:25:36 +0300 Subject: [PATCH] #22 add lava emitter --- src/controller.h | 2 +- src/format.h | 11 +++--- src/lara.h | 5 +-- src/level.h | 10 ++++-- src/sprite.h | 6 ++-- src/trigger.h | 87 ++++++++++++++++++++++++++++++++++++++++-------- src/utils.h | 4 +++ 7 files changed, 99 insertions(+), 26 deletions(-) diff --git a/src/controller.h b/src/controller.h index e06805d..d0f07c5 100644 --- a/src/controller.h +++ b/src/controller.h @@ -58,7 +58,7 @@ struct IGame { virtual void checkTrigger(Controller *controller, bool heavy) {} virtual int addSprite(TR::Entity::Type type, int room, int x, int y, int z, int frame = -1, bool empty = false) { return -1; } - virtual int addEntity(TR::Entity::Type type, int room, const vec3 &pos, float angle) { return -1; } + virtual Controller* addEntity(TR::Entity::Type type, int room, const vec3 &pos, float angle) { return NULL; } virtual bool invUse(TR::Entity::Type type) { return false; } virtual void invAdd(TR::Entity::Type type, int count = 1) {} diff --git a/src/format.h b/src/format.h index de7779d..a7f83e7 100644 --- a/src/format.h +++ b/src/format.h @@ -50,7 +50,7 @@ E( TRAP_BLADE ) \ E( TRAP_SPIKES ) \ E( TRAP_BOULDER ) \ - E( TRAP_DART ) \ + E( DART ) \ E( TRAP_DART_EMITTER ) \ E( DRAWBRIDGE ) \ E( TRAP_SLAM ) \ @@ -182,14 +182,14 @@ E( UNUSED_14 ) \ E( VIEW_TARGET ) \ E( WATERFALL ) \ - E( UNUSED_15 ) \ + E( NATLA_BULLET ) \ E( MUTANT_BULLET ) \ E( MUTANT_GRENADE ) \ E( UNUSED_16 ) \ E( UNUSED_17 ) \ - E( TRAP_LAVA_PARTICLE ) \ + E( LAVA_PARTICLE ) \ E( TRAP_LAVA_EMITTER ) \ - E( TRAP_FLAME ) \ + E( FLAME ) \ E( TRAP_FLAME_EMITTER ) \ E( TRAP_LAVA ) \ E( MUTANT_EGG_BIG ) \ @@ -299,6 +299,7 @@ namespace TR { SND_HIT_MUTANT = 142, SND_STOMP = 147, + SND_LAVA = 149, SND_FLAME = 150, SND_DART = 151, @@ -701,7 +702,7 @@ namespace TR { } bool castShadow() const { - return isLara() || isEnemy() || isActor() || type == TRAP_DART || type == TRAP_SWORD; + return isLara() || isEnemy() || isActor() || type == DART || type == TRAP_SWORD; } void getAxis(int &dx, int &dz) { diff --git a/src/lara.h b/src/lara.h index 1f00606..dd797ac 100644 --- a/src/lara.h +++ b/src/lara.h @@ -473,12 +473,13 @@ struct Lara : Character { //reset(12, vec3(34236, -2415, 14974), 0); // level 8b (sphinx) //reset(0, vec3(40913, -1012, 42252), PI); // level 8c //reset(30, vec3(69689, -8448, 34922), 330 * DEG2RAD); // Level 10a (cabin) - //reset(27, vec3(52631, -4352, 57893), 270 * DEG2RAD); // Level 10a (drill) + //reset(27, vec3(52631, -4352, 57893), 270 * DEG2RAD); // Level 10a (TNT / Cowboy) //reset(68, vec3(52458, -9984, 93724), 270 * DEG2RAD); // Level 10a (MrT) //reset(44, vec3(75803, -11008, 21097), 90 * DEG2RAD); // Level 10a (boat) //reset(50, vec3(53703, -18688, 13769), PI); // Level 10c (scion holder) //reset(19, vec3(35364, -512, 40199), PI * 0.5f); // Level 10c (lava flow) - //reset(9, vec3(69074, -14592, 25192), 0); // Level 10c (trap slam) + //reset(9, vec3(69074, -14592, 25192), 0); // Level 10c (trap slam) + //reset(21, vec3(47668, -10752, 32163), 0); // Level 10c (lava emitter) //reset(10, vec3(90443, 11264 - 256, 114614), PI, STAND_ONWATER); // villa mortal 2 #endif diff --git a/src/level.h b/src/level.h index 0a5c85b..30b86f3 100644 --- a/src/level.h +++ b/src/level.h @@ -253,7 +253,7 @@ struct Level : IGame { return Sprite::add(this, type, room, x, y, z, frame, empty); } - virtual int addEntity(TR::Entity::Type type, int room, const vec3 &pos, float angle) { + virtual Controller* addEntity(TR::Entity::Type type, int room, const vec3 &pos, float angle) { int index = level.entityAdd(type, room, int(pos.x), int(pos.y), int(pos.z), TR::angle(angle), -1); if (index > -1) { TR::Entity &e = level.entities[index]; @@ -265,8 +265,11 @@ struct Level : IGame { } if (e.isPickup()) e.intensity = 4096; + if (e.type == TR::Entity::LAVA_PARTICLE || e.type == TR::Entity::FLAME) + e.intensity = 0; // emissive + return controller; } - return index; + return NULL; } virtual bool invUse(TR::Entity::Type type) { @@ -501,6 +504,7 @@ struct Level : IGame { case TR::Entity::TRAP_BLADE : return new TrapBlade(this, index); case TR::Entity::TRAP_SPIKES : return new TrapSpikes(this, index); case TR::Entity::TRAP_BOULDER : return new TrapBoulder(this, index); + case TR::Entity::DART : return new Dart(this, index); case TR::Entity::TRAP_DART_EMITTER : return new TrapDartEmitter(this, index); case TR::Entity::DRAWBRIDGE : return new Drawbridge(this, index); case TR::Entity::BLOCK_1 : @@ -532,6 +536,8 @@ struct Level : IGame { case TR::Entity::CENTAUR_STATUE : return new CentaurStatue(this, index); case TR::Entity::CABIN : return new Cabin(this, index); case TR::Entity::TRAP_FLAME_EMITTER : return new TrapFlameEmitter(this, index); + case TR::Entity::LAVA_PARTICLE : return new LavaParticle(this, index); + case TR::Entity::TRAP_LAVA_EMITTER : return new TrapLavaEmitter(this, index); case TR::Entity::BOAT : return new Boat(this, index); case TR::Entity::EARTHQUAKE : return new Earthquake(this, index); case TR::Entity::MUTANT_EGG_SMALL : diff --git a/src/sprite.h b/src/sprite.h index 9b8b0fc..137e7d4 100644 --- a/src/sprite.h +++ b/src/sprite.h @@ -15,7 +15,9 @@ struct Sprite : Controller { float time; vec3 velocity; - Sprite(IGame *game, int entity, bool instant = true, int frame = FRAME_ANIMATED) : Controller(game, entity), instant(instant), flag(frame), time(0), velocity(0) { + BlendMode blendMode; + + Sprite(IGame *game, int entity, bool instant = true, int frame = FRAME_ANIMATED) : Controller(game, entity), instant(instant), flag(frame), time(0), velocity(0), blendMode(bmAlpha) { if (frame >= 0) { // specific frame this->frame = frame; } else if (frame == FRAME_RANDOM) { // random frame @@ -67,7 +69,7 @@ struct Sprite : Controller { } virtual void render(Frustum *frustum, MeshBuilder *mesh, Shader::Type type, bool caustics) { - Core::setBlending(bmAlpha); + Core::setBlending(blendMode); Core::active.shader->setParam(uBasis, Basis(Core::mViewInv.getRot(), pos)); mesh->renderSprite(-(getEntity().modelIndex + 1), frame); Core::setBlending(bmNone); diff --git a/src/trigger.h b/src/trigger.h index 7f964af..0be2a1c 100644 --- a/src/trigger.h +++ b/src/trigger.h @@ -65,6 +65,7 @@ struct Dart : Controller { Dart(IGame *game, int entity) : Controller(game, entity), armed(true) { dir = vec3(sinf(angle.y), 0, cosf(angle.y)); + activate(); } virtual void update() { @@ -112,15 +113,8 @@ struct TrapDartEmitter : Controller { vec3 p = pos + vec3(0.0f, -512.0f, 256.0f).rotateY(PI - entity.rotation); - int index = level->entityAdd(TR::Entity::TRAP_DART, getRoomIndex(), int(p.x), int(p.y), int(p.z), entity.rotation, -1); - if (index > -1) { - Dart *dart = new Dart(game, index); - dart->activate(); - level->entities[index].controller = dart; - } - + game->addEntity(TR::Entity::DART, getRoomIndex(), p, entity.rotation); Sprite::add(game, TR::Entity::SMOKE, entity.room, (int)p.x, (int)p.y, (int)p.z); - game->playSound(TR::SND_DART, p, Sound::Flags::PAN); } @@ -140,7 +134,7 @@ struct Flame : Sprite { int roomIndex = controller->getRoomIndex(); vec3 pos = controller->pos; - int index = level->entityAdd(TR::Entity::TRAP_FLAME, roomIndex, int(pos.x), int(pos.y), int(pos.z), 0, 0); + int index = level->entityAdd(TR::Entity::FLAME, roomIndex, int(pos.x), int(pos.y), int(pos.z), 0, 0); if (index > -1) { flame = new Flame(game, index, jointIndex); level->entities[index].controller = flame; @@ -213,6 +207,73 @@ struct TrapFlameEmitter : Controller { } }; + +#define LAVA_PARTICLE_DAMAGE 10 +#define LAVA_V_SPEED -165 +#define LAVA_H_SPEED 32 +#define LAVA_EMITTER_RANGE (1024 * 10) + +struct LavaParticle : Sprite { + int bounces; + + LavaParticle(IGame *game, int entity) : Sprite(game, entity, false, Sprite::FRAME_RANDOM), bounces(0) { + float speed = randf() * LAVA_H_SPEED; + velocity = vec3(cosf(angle.y) * speed, randf() * LAVA_V_SPEED, sinf(angle.y) * speed); + blendMode = bmAdd; + activate(); + } + + virtual void update() { + applyGravity(velocity.y); + Sprite::update(); + + TR::Level::FloorInfo info; + level->getFloorInfo(getRoomIndex(), int(pos.x), int(pos.y), int(pos.z), info); + + bool hit = false; + if (!bounces) { + Controller *lara = (Controller*)game->getLara(); + if ((hit = lara->collide(Sphere(pos, 0.0f)))) + lara->hit(LAVA_PARTICLE_DAMAGE, this); + } + + if (hit || pos.y > info.floor || pos.y < info.ceiling) { + if (hit || ++bounces > 4) { + level->entityRemove(entity); + delete this; + return; + } + getEntity().intensity = bounces * 2048 - 1; + + if (pos.y > info.floor) pos.y = float(info.floor); + if (pos.y < info.ceiling) pos.y = float(info.ceiling); + + velocity = velocity.reflect(vec3(0, 1, 0)) * 0.5f; + } + } +}; + +struct TrapLavaEmitter : Controller { + float timer; + + TrapLavaEmitter(IGame *game, int entity) : Controller(game, entity), timer(0.0f) {} + + void virtual update() { + vec3 d = (game->getLara()->pos - pos).abs(); + + if (!isActive() || max(d.x, d.y, d.z) > LAVA_EMITTER_RANGE) return; + + if (timer <= 0.0f) { + game->addEntity(TR::Entity::LAVA_PARTICLE, getRoomIndex(), pos, PI * 2.0f * randf()); + game->playSound(TR::SND_LAVA, pos, Sound::PAN); + timer += 1.0f / 30.0f; + } else + timer -= Core::deltaTime; + } +}; + + + #define BOULDER_DAMAGE_GROUND 1000 #define BOULDER_DAMAGE_AIR 100 @@ -1118,11 +1179,9 @@ struct CentaurStatue : Controller { if ((pos - game->getLara()->pos).length() < CENTAUR_STATUE_RANGE) { explode(0xFFFFFFFF); game->playSound(TR::SND_EXPLOSION, pos, Sound::PAN); - int index = game->addEntity(TR::Entity::ENEMY_CENTAUR, getRoomIndex(), pos, angle.y); - if (index > -1) { - Controller *controller = (Controller*)level->entities[index].controller; - controller->animation.setAnim(7, -36); - } + Controller *enemy = game->addEntity(TR::Entity::ENEMY_CENTAUR, getRoomIndex(), pos, angle.y); + if (enemy) + enemy->animation.setAnim(7, -36); } } }; diff --git a/src/utils.h b/src/utils.h index 190ddad..862f407 100644 --- a/src/utils.h +++ b/src/utils.h @@ -251,6 +251,10 @@ struct vec3 { vec3 normal() const { float s = length(); return s == 0.0f ? (*this) : (*this)*(1.0f/s); } vec3 axisXZ() const { return (fabsf(x) > fabsf(z)) ? vec3(float(sign(x)), 0, 0) : vec3(0, 0, float(sign(z))); } + vec3 reflect(const vec3 &n) const { + return *this - n * (dot(n) * 2.0f); + } + vec3 lerp(const vec3 &v, const float t) const { if (t <= 0.0f) return *this; if (t >= 1.0f) return v;