1
0
mirror of https://github.com/XProger/OpenLara.git synced 2025-08-17 18:36:43 +02:00
This commit is contained in:
XProger
2018-07-22 23:04:50 +03:00
parent a22381fed5
commit 0e240b7f0b
6 changed files with 226 additions and 16 deletions

View File

@@ -92,8 +92,8 @@ struct IGame {
virtual bool invChooseKey(int playerIndex, TR::Entity::Type hole) { return false; } virtual bool invChooseKey(int playerIndex, TR::Entity::Type hole) { return false; }
virtual Sound::Sample* playSound(int id, const vec3 &pos = vec3(0.0f), int flags = 0) const { return NULL; } virtual Sound::Sample* playSound(int id, const vec3 &pos = vec3(0.0f), int flags = 0) const { return NULL; }
virtual void playTrack(uint8 track) {} virtual void playTrack(uint8 track, bool background = false) {}
virtual void stopTrack() {} virtual void stopTrack() {}
}; };
struct Controller { struct Controller {

View File

@@ -348,6 +348,7 @@ struct Enemy : Character {
return false; return false;
thinkTime -= 1.0f / 30.0f; thinkTime -= 1.0f / 30.0f;
int zoneOld = zone;
updateZone(); updateZone();
target = (Character*)game->getLara(pos); target = (Character*)game->getLara(pos);
@@ -422,6 +423,9 @@ struct Enemy : Character {
if (path && this->box != path->boxes[path->index - 1] && this->box != path->boxes[path->index]) if (path && this->box != path->boxes[path->index - 1] && this->box != path->boxes[path->index])
targetBoxOld = -1; targetBoxOld = -1;
if (zoneOld != zone)
targetBoxOld = -1;
if (targetBoxOld != targetBox) { if (targetBoxOld != targetBox) {
if (findPath(stepHeight, dropHeight, getEntity().isBigEnemy())) if (findPath(stepHeight, dropHeight, getEntity().isBigEnemy()))
nextWaypoint(); nextWaypoint();
@@ -512,7 +516,7 @@ struct Enemy : Character {
return false; return false;
} }
void shot(TR::Entity::Type type, int joint, const vec3 &offset) { void shot(TR::Entity::Type type, int joint, const vec3 &offset, float rx, float ry) {
vec3 from = getJoint(joint) * offset; vec3 from = getJoint(joint) * offset;
vec3 to = target->getBoundingBox().center(); vec3 to = target->getBoundingBox().center();
@@ -520,11 +524,15 @@ struct Enemy : Character {
if (bullet) { if (bullet) {
vec3 dir = to - from; vec3 dir = to - from;
vec3 ang = vec3(-atan2f(dir.y, sqrtf(dir.x * dir.x + dir.z * dir.z)), atan2f(dir.x, dir.z), 0.0f); vec3 ang = vec3(-atan2f(dir.y, sqrtf(dir.x * dir.x + dir.z * dir.z)), atan2f(dir.x, dir.z), 0.0f);
ang += vec3(randf() * 2.0f - 1.0f, randf() * 2.0f - 1.0f, 0.0f) * (1.5f * DEG2RAD); ang += vec3(rx, ry, 0.0f);
bullet->setAngle(ang); bullet->setAngle(ang);
} }
} }
void shot(TR::Entity::Type type, int joint, const vec3 &offset) {
shot(type, joint, offset, (randf() * 2.0f - 1.0f) * (1.5f * DEG2RAD), (randf() * 2.0f - 1.0f) * (1.5f * DEG2RAD));
}
bool isVisible() { bool isVisible() {
for (int i = 0; i < 2; i++) { for (int i = 0; i < 2; i++) {
ICamera *camera = game->getCamera(i); ICamera *camera = game->getCamera(i);
@@ -2777,7 +2785,7 @@ struct SkaterBoy : Human {
fullChestRotation = state == STATE_STAND_FIRE || state == STATE_MOVE_FIRE; fullChestRotation = state == STATE_STAND_FIRE || state == STATE_MOVE_FIRE;
if (health < 120) if (health < 120)
game->playTrack(56); game->playTrack(56, true);
switch (state) { switch (state) {
case STATE_STOP : case STATE_STOP :
@@ -2982,10 +2990,196 @@ struct MrT : Human {
} }
}; };
#define NATLA_FIRE_ANGLE (30 * DEG2RAD)
#define NATLA_FAINT_TIME 16.0f
#define NATLA_HALF_HEALTH 200.0f
#define NATLA_FAINT_HEALTH -8192.0f
#define NATLA_LIFT_SPEED MUTANT_LIFT_SPEED
struct Natla : Human { struct Natla : Human {
Natla(IGame *game, int entity) : Human(game, entity, 400) {} enum {
STATE_NONE,
STATE_STOP,
STATE_FLY,
STATE_RUN,
STATE_AIM,
STATE_FAINT,
STATE_FIRE,
STATE_FALL,
STATE_STAND,
STATE_DEATH,
};
enum {
FLAG_FLY = 1,
};
Natla(IGame *game, int entity) : Human(game, entity, 400) {
jointChest = 1;
jointHead = 2;
}
int stage1() {
flying = (flags.unused & FLAG_FLY);
stepHeight = 256;
dropHeight = -256;
if (flying) {
stepHeight *= 80;
dropHeight *= 80;
}
if (!think(false))
return state;
timer += Core::deltaTime;
bool canShot = target && target->health > 0.0f && targetIsVisible(HUMAN_DIST_SHOT);
if (canShot && state == STATE_FLY && flying && rand() < 256)
flags.unused &= ~FLAG_FLY;
else if (!canShot)
flags.unused |= FLAG_FLY;
flying = (flags.unused & FLAG_FLY);
if (state == nextState)
nextState = STATE_NONE;
switch (state) {
case STATE_STOP :
timer = 0.0f;
return flying ? STATE_FLY : STATE_AIM;
case STATE_FLY : {
if (timer >= 1.0f) {
{ //if (canShot) { ???
game->playSound(TR::SND_NATLA_SHOT, pos, Sound::PAN);
shot(TR::Entity::CENTAUR_BULLET, 4, vec3(5.0f, 220.0f, 7.0f));
}
timer -= 1.0f;
}
int16 roomIndex = getRoomIndex();
TR::Room::Sector *sector = level->getSector(roomIndex, pos);
float floor = level->getFloor(sector, pos) - 128.0f;
if (!flying && pos.y >= floor)
return STATE_STOP;
break;
}
case STATE_AIM :
if (nextState != STATE_NONE)
return nextState;
return canShot ? STATE_FIRE : STATE_STOP;
case STATE_FIRE :
if (nextState != STATE_NONE)
return state;
game->playSound(TR::SND_NATLA_SHOT, pos, Sound::PAN);
shot(TR::Entity::CENTAUR_BULLET, 4, vec3(5.0f, 220.0f, 7.0f));
shot(TR::Entity::CENTAUR_BULLET, 4, vec3(5.0f, 220.0f, 7.0f), 0.0f, (randf() * 2.0f - 1.0f) * (25.0f * DEG2RAD));
shot(TR::Entity::CENTAUR_BULLET, 4, vec3(5.0f, 220.0f, 7.0f), 0.0f, (randf() * 2.0f - 1.0f) * (25.0f * DEG2RAD));
nextState = STATE_STOP;
break;
}
return state;
}
int stage2() {
stepHeight = 256;
dropHeight = -256;
flying = false;
if (!think(true))
return state;
timer += Core::deltaTime;
bool canShot = target && target->health > 0.0f && fabsf(targetAngle) < NATLA_FIRE_ANGLE && targetIsVisible(HUMAN_DIST_SHOT);
switch (state) {
case STATE_RUN :
case STATE_STAND :
if (timer >= 20.0f / 30.0f) {
{ // if (canShot) { ???
game->playSound(TR::SND_NATLA_SHOT, pos, Sound::PAN);
shot(TR::Entity::MUTANT_BULLET, 4, vec3(5.0f, 220.0f, 7.0f));
}
timer -= 20.0f / 30.0f;
}
return canShot ? STATE_STAND : STATE_RUN;
case STATE_FLY :
health = NATLA_FAINT_HEALTH;
return STATE_FALL;
case STATE_STOP :
case STATE_AIM :
case STATE_FIRE :
health = NATLA_FAINT_HEALTH;
return STATE_FAINT;
}
return state;
}
virtual int getStateGround() {
if (health > NATLA_HALF_HEALTH)
return stage1();
return stage2();
}
virtual int getStateDeath() {
switch (state) {
case STATE_FALL : {
int16 roomIndex = getRoomIndex();
TR::Room::Sector *sector = level->getSector(roomIndex, pos);
float floor = level->getFloor(sector, pos);
if (pos.y >= floor) {
pos.y = floor;
timer = 0.0f;
return STATE_FAINT;
}
return state;
}
case STATE_FAINT : {
timer += Core::deltaTime;
if (timer >= NATLA_FAINT_TIME) {
health = NATLA_HALF_HEALTH;
timer = 0.0f;
flags.unused = 0;
game->playTrack(54, true);
return STATE_STAND;
}
return state;
}
}
return STATE_DEATH;
}
virtual void updateVelocity() {
if (state == STATE_FLY) {
angle.y += targetAngle;
updateJoints();
angle.y -= targetAngle;
}
Enemy::updateVelocity();
}
virtual void updatePosition() {
if (flying) {
stand = STAND_AIR;
lift(target->pos.y - pos.y, NATLA_LIFT_SPEED);
}
turn(true, state == STATE_RUN ? HUMAN_TURN_FAST : HUMAN_TURN_SLOW);
Enemy::updatePosition();
setOverrides(state != STATE_FAINT, jointChest, jointHead);
lookAt(target);
stand = STAND_GROUND;
}
}; };
struct Dog : Enemy { struct Dog : Enemy {

View File

@@ -960,6 +960,8 @@ namespace TR {
SND_STAIRS2SLOPE = 119, SND_STAIRS2SLOPE = 119,
SND_NATLA_SHOT = 123,
SND_HIT_SKATEBOY = 132, SND_HIT_SKATEBOY = 132,
SND_HIT_MUTANT = 142, SND_HIT_MUTANT = 142,
@@ -2250,7 +2252,7 @@ namespace TR {
ByteFlags flipmaps[MAX_FLIPMAP_COUNT]; ByteFlags flipmaps[MAX_FLIPMAP_COUNT];
ByteFlags tracks[MAX_TRACKS_COUNT]; ByteFlags tracks[MAX_TRACKS_COUNT];
uint16 fogColor; uint16 fogColor;
union { union {
struct { uint16 track:8, flipped:1; }; struct { uint16 track:8, flipped:1; };
uint16 value; uint16 value;

View File

@@ -527,14 +527,16 @@ struct Lara : Character {
//reset(57, vec3(71081, 5632, 73042), 0); // Level 10a (Skaterboy) //reset(57, vec3(71081, 5632, 73042), 0); // Level 10a (Skaterboy)
//reset(68, vec3(52458, -9984, 93724), 270 * DEG2RAD); // Level 10a (MrT) //reset(68, vec3(52458, -9984, 93724), 270 * DEG2RAD); // Level 10a (MrT)
//reset(44, vec3(75803, -11008, 21097), 90 * DEG2RAD); // Level 10a (boat) //reset(44, vec3(75803, -11008, 21097), 90 * DEG2RAD); // Level 10a (boat)
//reset(47, vec3(50546, -13056, 53783), 270 * DEG2RAD); // Level 10b (trap door slope) //reset(47, vec3(50546, -13056, 53783), 270 * DEG2RAD); // Level 10b (trap door slope)
//reset(59, vec3(42907, -13056, 63012), 270 * DEG2RAD); // Level 10b (doppelganger) //reset(59, vec3(42907, -13056, 63012), 270 * DEG2RAD); // Level 10b (doppelganger)
//reset(53, vec3(39617, -18385, 48950), 180 * DEG2RAD); // Level 10b (centaur) //reset(53, vec3(39617, -18385, 48950), 180 * DEG2RAD); // Level 10b (centaur)
//reset(50, vec3(52122, -18688, 47313), 150 * DEG2RAD); // Level 10b (scion holder pickup) //reset(50, vec3(52122, -18688, 47313), 150 * DEG2RAD); // Level 10b (scion holder pickup)
//reset(50, vec3(53703, -18688, 13769), PI); // Level 10c (scion holder) //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(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(21, vec3(47668, -10752, 32163), 0); // Level 10c (lava emitter)
//reset(29, vec3(61586, -439, 51734), PI * 0.5f); // Level 10c (precise falling)
//reset(33, vec3(64641, 9578, 61861), 0); // Level 10c (Natla)
//reset(10, vec3(90443, 11264 - 256, 114614), PI, STAND_ONWATER); // villa mortal 2 //reset(10, vec3(90443, 11264 - 256, 114614), PI, STAND_ONWATER); // villa mortal 2
//dbgBoxes = NULL; //dbgBoxes = NULL;
@@ -1720,7 +1722,7 @@ struct Lara : Character {
} }
int doTutorial(int track) { int doTutorial(int track) {
if (level->version == TR::VER_TR1_PC || level->version == TR::VER_TR1_PSX) if (level->version & TR::VER_TR1)
switch (track) { // GYM tutorial routine switch (track) { // GYM tutorial routine
case 28 : if (level->state.tracks[track].once && state == STATE_UP_JUMP) track = 29; break; case 28 : if (level->state.tracks[track].once && state == STATE_UP_JUMP) track = 29; break;
case 37 : case 37 :
@@ -2036,7 +2038,7 @@ struct Lara : Character {
if (!(level->state.progress.secrets & (1 << cmd.args))) { if (!(level->state.progress.secrets & (1 << cmd.args))) {
level->state.progress.secrets |= 1 << cmd.args; level->state.progress.secrets |= 1 << cmd.args;
if (!game->playSound(TR::SND_SECRET, pos)) if (!game->playSound(TR::SND_SECRET, pos))
game->playTrack(TR::TRACK_TR1_SECRET); game->playTrack(TR::TRACK_TR1_SECRET, true);
} }
break; break;
} }

View File

@@ -607,7 +607,7 @@ struct Level : IGame {
void stopChannel(Sound::Sample *channel) { void stopChannel(Sound::Sample *channel) {
if (channel == sndTrack) { if (channel == sndTrack) {
sndTrack = NULL; sndTrack = NULL;
if (level.state.flags.track == TR::LEVEL_INFO[level.id].track) // play ambient track if (level.state.flags.track != TR::LEVEL_INFO[level.id].track) // play ambient track
playTrack(0); playTrack(0);
} }
} }
@@ -636,7 +636,19 @@ struct Level : IGame {
delete req; delete req;
} }
virtual void playTrack(uint8 track) { static void playAsyncBG(Stream *stream, void *userData) {
TrackRequest *req = (TrackRequest*)userData;
if (stream)
Sound::play(stream, NULL, 1.0f, 1.0f, req->flags);
delete req;
}
virtual void playTrack(uint8 track, bool background = false) {
if (background) {
TR::getGameTrack(level.version, track, playAsyncBG, new TrackRequest(this, Sound::MUSIC));
return;
}
if (track == 0) if (track == 0)
track = TR::LEVEL_INFO[level.id].track; track = TR::LEVEL_INFO[level.id].track;

View File

@@ -857,7 +857,7 @@ struct Video {
height = (frame.height + 15) / 16 * 16; height = (frame.height + 15) / 16 * 16;
fps = 150 / (frame.size / VIDEO_CHUNK_SIZE); fps = 150 / (frame.size / VIDEO_CHUNK_SIZE);
fps = (fps < 20) ? 15 : 30; fps = (fps < 20) ? 15 : 30;
//fps = int(fps * 44100 / 37800);
stream->setPos(pos); stream->setPos(pos);
vFrameIndex = aFrameIndex = -1; vFrameIndex = aFrameIndex = -1;