diff --git a/src/controller.h b/src/controller.h index 9ba8393..a6ae3b0 100644 --- a/src/controller.h +++ b/src/controller.h @@ -31,6 +31,7 @@ struct ICamera { struct IGame { virtual ~IGame() {} virtual void loadLevel(TR::LevelID id) {} + virtual void loadNextLevel() {} virtual void loadGame(int slot) {} virtual void saveGame(int slot) {} virtual void applySettings(const Core::Settings &settings) {} @@ -56,7 +57,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 addEnemy(TR::Entity::Type type, int room, const vec3 &pos, float angle) { return -1; } + virtual int addEntity(TR::Entity::Type type, int room, const vec3 &pos, float angle) { return -1; } virtual bool invUse(TR::Entity::Type type) { return false; } virtual void invAdd(TR::Entity::Type type, int count = 1) {} @@ -527,10 +528,11 @@ struct Controller { if (animation.isFrameActive(frame)) { if (cmd == TR::ANIM_CMD_EFFECT) { switch (fx) { - case TR::Effect::ROTATE_180 : angle.y = angle.y + PI; break; - case TR::Effect::FLOOR_SHAKE : game->setEffect(this, TR::Effect(fx)); break; - case TR::Effect::FLIP_MAP : level->isFlipped = !level->isFlipped; break; - default : cmdEffect(fx); break; + case TR::Effect::ROTATE_180 : angle.y = angle.y + PI; break; + case TR::Effect::FLOOR_SHAKE : game->setEffect(this, TR::Effect(fx)); break; + case TR::Effect::FINISH_LEVEL : game->loadNextLevel(); break; + case TR::Effect::FLIP_MAP : level->isFlipped = !level->isFlipped; break; + default : cmdEffect(fx); break; } } else game->playSound(fx, pos, Sound::Flags::PAN); diff --git a/src/enemy.h b/src/enemy.h index 192c0cd..4cdaf3d 100644 --- a/src/enemy.h +++ b/src/enemy.h @@ -1293,4 +1293,114 @@ struct ScionTarget : Enemy { }; +struct Human : Enemy { + enum { + STATE_NONE, + STATE_STOP, + STATE_WALK, + STATE_RUN, + STATE_AIM, + STATE_DEATH, + STATE_UNKNOWN, + STATE_FIRE + }; + + int animDeath; + + Human(IGame *game, int entity, float health) : Enemy(game, entity, health, 100, 375.0f, 1.0f), animDeath(-1) { + jointChest = 7; + jointHead = 8; + } + + virtual void deactivate(bool removeFromList = false) { + if (health <= 0.0f) + onDead(); + Enemy::deactivate(removeFromList); + } + + virtual int getStateDeath() { + return (animDeath == -1 || state == STATE_DEATH || state == STATE_NONE) ? STATE_DEATH : animation.setAnim(animDeath); + } + + virtual int getStateGround() { + if (!think(true)) + return state; + return state; + } + + virtual void updatePosition() { + Enemy::updatePosition(); + setOverrides(true, jointChest, jointHead); + lookAt(target); + } + + virtual void onDead() {} +}; + + +struct Larson : Human { + + Larson(IGame *game, int entity) : Human(game, entity, 50) { + animDeath = 15; + } +}; + + +struct Pierre : Human { + + Pierre(IGame *game, int entity) : Human(game, entity, 70) { + animDeath = 12; + } + + virtual void onDead() { + if (level->id == TR::LEVEL_7B) { + game->addEntity(TR::Entity::MAGNUMS, getRoomIndex(), pos, 0); + game->addEntity(TR::Entity::SCION_DROP, getRoomIndex(), pos, 0); + game->addEntity(TR::Entity::KEY_ITEM_1, getRoomIndex(), pos, 0); + } + } +}; + + +struct SkaterBoy : Human { + + SkaterBoy(IGame *game, int entity) : Human(game, entity, 125) { + animDeath = 13; + } + + virtual void onDead() { + game->addEntity(TR::Entity::UZIS, getRoomIndex(), pos, 0); + } +}; + + +struct Cowboy : Human { + + Cowboy(IGame *game, int entity) : Human(game, entity, 150) { + animDeath = 7; + } + + virtual void onDead() { + game->addEntity(TR::Entity::MAGNUMS, getRoomIndex(), pos, 0); + } +}; + + +struct MrT : Human { + + MrT(IGame *game, int entity) : Human(game, entity, 200) { + animDeath = 14; + } + + virtual void onDead() { + game->addEntity(TR::Entity::SHOTGUN, getRoomIndex(), pos, 0); + } +}; + + +struct Natla : Human { + + Natla(IGame *game, int entity) : Human(game, entity, 400) {} +}; + #endif \ No newline at end of file diff --git a/src/lara.h b/src/lara.h index 8662341..764e02b 100644 --- a/src/lara.h +++ b/src/lara.h @@ -468,11 +468,13 @@ struct Lara : Character { //reset(99, vec3(45562, -3328, 63366), 225 * DEG2RAD); // level 7a (flipmap) //reset(77, vec3(36943, -4096, 62821), 270 * DEG2RAD); // level 7b (heavy trigger) //reset(90, vec3(19438, 3840, 78341), 90 * DEG2RAD); // level 7b (statues) - //reset(57, vec3(54844, -3328, 53145), 0); // level 8b (bridge switch + //reset(90, vec3(29000, 3840 - 512, 78341), 90 * DEG2RAD); // level 7b (statues) + //reset(57, vec3(54844, -3328, 53145), 0); // level 8b (bridge switch) //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(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) @@ -1841,7 +1843,7 @@ struct Lara : Character { cameraTarget = (Controller*)level->entities[cmd.args].controller; break; case TR::Action::END : - game->loadLevel(level->id == TR::LEVEL_10C ? TR::TITLE : TR::LevelID(level->id + 1)); + game->loadNextLevel(); break; case TR::Action::SOUNDTRACK : { int track = doTutorial(cmd.args); diff --git a/src/level.h b/src/level.h index a3001e3..46a383b 100644 --- a/src/level.h +++ b/src/level.h @@ -69,6 +69,10 @@ struct Level : IGame { new Stream(buf, loadAsync); } + virtual void loadNextLevel() { + loadLevel(level.id == TR::LEVEL_10C ? TR::TITLE : TR::LevelID(level.id + 1)); + } + virtual void loadGame(int slot) { // } @@ -249,14 +253,18 @@ struct Level : IGame { return Sprite::add(this, type, room, x, y, z, frame, empty); } - virtual int addEnemy(TR::Entity::Type type, int room, const vec3 &pos, float angle) { + virtual int 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]; - Controller *enemy = initController(index); - e.controller = enemy; - e.flags.active = TR::ACTIVE; - enemy->activate(); + Controller *controller = initController(index); + e.controller = controller; + if (e.isEnemy()) { + e.flags.active = TR::ACTIVE; + controller->activate(); + } + if (e.isPickup()) + e.intensity = 4096; } return index; } @@ -464,13 +472,13 @@ struct Level : IGame { case TR::Entity::ENEMY_CROCODILE_LAND : case TR::Entity::ENEMY_CROCODILE_WATER : case TR::Entity::ENEMY_PUMA : - case TR::Entity::ENEMY_GORILLA : - case TR::Entity::ENEMY_LARSON : - case TR::Entity::ENEMY_PIERRE : - case TR::Entity::ENEMY_SKATEBOY : - case TR::Entity::ENEMY_COWBOY : - case TR::Entity::ENEMY_MR_T : - case TR::Entity::ENEMY_NATLA : return new Enemy(this, index, 100, 10, 0.0f, 0.0f); + case TR::Entity::ENEMY_GORILLA : return new Enemy(this, index, 100, 10, 0.0f, 0.0f); + case TR::Entity::ENEMY_LARSON : return new Larson(this, index); + case TR::Entity::ENEMY_PIERRE : return new Pierre(this, index); + case TR::Entity::ENEMY_SKATEBOY : return new SkaterBoy(this, index); + case TR::Entity::ENEMY_COWBOY : return new Cowboy(this, index); + case TR::Entity::ENEMY_MR_T : return new MrT(this, index); + case TR::Entity::ENEMY_NATLA : return new Natla(this, index); case TR::Entity::ENEMY_GIANT_MUTANT : return new GiantMutant(this, index); case TR::Entity::DOOR_1 : case TR::Entity::DOOR_2 : diff --git a/src/trigger.h b/src/trigger.h index 94b6e18..7f964af 100644 --- a/src/trigger.h +++ b/src/trigger.h @@ -1118,7 +1118,7 @@ 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->addEnemy(TR::Entity::ENEMY_CENTAUR, getRoomIndex(), pos, angle.y); + 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); @@ -1212,7 +1212,7 @@ struct MutantEgg : Controller { animation.setState(STATE_EXPLOSION); layers[0].mask = 0xffffffff & ~(1 << 24); explode(0x00fffe00); - game->addEnemy(enemy, getRoomIndex(), pos, angle.y); + game->addEntity(enemy, getRoomIndex(), pos, angle.y); } } Controller::update();