1
0
mirror of https://github.com/XProger/OpenLara.git synced 2025-08-16 01:54:38 +02:00

#22 add lava emitter

This commit is contained in:
XProger
2017-10-13 10:25:36 +03:00
parent 43088756fd
commit 7d43b2426c
7 changed files with 99 additions and 26 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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