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:
@@ -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) {}
|
||||
|
11
src/format.h
11
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) {
|
||||
|
@@ -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
|
||||
|
||||
|
10
src/level.h
10
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 :
|
||||
|
@@ -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);
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@@ -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;
|
||||
|
Reference in New Issue
Block a user