mirror of
https://github.com/XProger/OpenLara.git
synced 2025-08-14 17:14:29 +02:00
#3 cutscenes fix, draw weapon animation command
This commit is contained in:
@@ -66,7 +66,9 @@ struct Controller {
|
|||||||
layers[0].mask = 0xFFFFFFFF;
|
layers[0].mask = 0xFFFFFFFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
void meshSwap(int layer, uint32 model, uint32 mask = 0xFFFFFFFF) {
|
void meshSwap(int layer, int16 model, uint32 mask = 0xFFFFFFFF) {
|
||||||
|
if (model < 0) return;
|
||||||
|
|
||||||
if (!layers) initMeshOverrides();
|
if (!layers) initMeshOverrides();
|
||||||
|
|
||||||
TR::Model &m = level->models[model];
|
TR::Model &m = level->models[model];
|
||||||
@@ -148,6 +150,10 @@ struct Controller {
|
|||||||
return getEntity().room;
|
return getEntity().room;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual vec3& getPos() {
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
int getOverlap(int fromX, int fromY, int fromZ, int toX, int toZ) const {
|
int getOverlap(int fromX, int fromY, int fromZ, int toX, int toZ) const {
|
||||||
int dx, dz;
|
int dx, dz;
|
||||||
TR::Room::Sector &s = level->getSector(getEntity().room, fromX, fromZ, dx, dz);
|
TR::Room::Sector &s = level->getSector(getEntity().room, fromX, fromZ, dx, dz);
|
||||||
@@ -357,7 +363,7 @@ struct Controller {
|
|||||||
virtual void cmdJump(const vec3 &vel) {}
|
virtual void cmdJump(const vec3 &vel) {}
|
||||||
virtual void cmdKill() {}
|
virtual void cmdKill() {}
|
||||||
virtual void cmdEmpty() {}
|
virtual void cmdEmpty() {}
|
||||||
|
virtual void cmdEffect(int fx) { ASSERT(false); } // not implemented
|
||||||
|
|
||||||
virtual void updateAnimation(bool commands) {
|
virtual void updateAnimation(bool commands) {
|
||||||
animation.update();
|
animation.update();
|
||||||
@@ -384,8 +390,7 @@ struct Controller {
|
|||||||
switch (fx) {
|
switch (fx) {
|
||||||
case TR::EFFECT_ROTATE_180 : angle.y = angle.y + PI; break;
|
case TR::EFFECT_ROTATE_180 : angle.y = angle.y + PI; break;
|
||||||
case TR::EFFECT_LARA_BUBBLES : doBubbles(); break;
|
case TR::EFFECT_LARA_BUBBLES : doBubbles(); break;
|
||||||
case TR::EFFECT_LARA_HANDSFREE : break;
|
default : cmdEffect(fx); break;
|
||||||
default : LOG("unknown special cmd %d (anim %d)\n", fx, animation.index);
|
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
playSound(fx, pos, Sound::Flags::PAN);
|
playSound(fx, pos, Sound::Flags::PAN);
|
||||||
|
16
src/format.h
16
src/format.h
@@ -356,6 +356,10 @@ namespace TR {
|
|||||||
enum Type : int16 {
|
enum Type : int16 {
|
||||||
NONE = -1,
|
NONE = -1,
|
||||||
LARA = 0,
|
LARA = 0,
|
||||||
|
LARA_PISTOLS = 1,
|
||||||
|
LARA_SHOTGUN = 2,
|
||||||
|
LARA_MAGNUMS = 3,
|
||||||
|
LARA_UZIS = 4,
|
||||||
|
|
||||||
ENEMY_TWIN = 6,
|
ENEMY_TWIN = 6,
|
||||||
ENEMY_WOLF = 7,
|
ENEMY_WOLF = 7,
|
||||||
@@ -814,8 +818,9 @@ namespace TR {
|
|||||||
void *cameraController;
|
void *cameraController;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
uint16 muzzleFlash;
|
int16 muzzleFlash;
|
||||||
uint16 puzzleSet;
|
int16 puzzleSet;
|
||||||
|
int16 weapons[4];
|
||||||
} extra;
|
} extra;
|
||||||
|
|
||||||
Level(Stream &stream, bool demo) {
|
Level(Stream &stream, bool demo) {
|
||||||
@@ -1012,10 +1017,17 @@ namespace TR {
|
|||||||
memset(secrets, 0, MAX_SECRETS_COUNT * sizeof(secrets[0]));
|
memset(secrets, 0, MAX_SECRETS_COUNT * sizeof(secrets[0]));
|
||||||
// get special models indices
|
// get special models indices
|
||||||
memset(&extra, 0, sizeof(extra));
|
memset(&extra, 0, sizeof(extra));
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
extra.weapons[i] = -1;
|
||||||
|
|
||||||
for (int i = 0; i < modelsCount; i++)
|
for (int i = 0; i < modelsCount; i++)
|
||||||
switch (models[i].type) {
|
switch (models[i].type) {
|
||||||
case Entity::MUZZLE_FLASH : extra.muzzleFlash = i; break;
|
case Entity::MUZZLE_FLASH : extra.muzzleFlash = i; break;
|
||||||
case Entity::HOLE_PUZZLE_SET : extra.puzzleSet = i; break;
|
case Entity::HOLE_PUZZLE_SET : extra.puzzleSet = i; break;
|
||||||
|
case Entity::LARA_PISTOLS : extra.weapons[0] = i; break;
|
||||||
|
case Entity::LARA_SHOTGUN : extra.weapons[1] = i; break;
|
||||||
|
case Entity::LARA_MAGNUMS : extra.weapons[2] = i; break;
|
||||||
|
case Entity::LARA_UZIS : extra.weapons[3] = i; break;
|
||||||
default : ;
|
default : ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
66
src/lara.h
66
src/lara.h
@@ -176,7 +176,7 @@ struct Lara : Character {
|
|||||||
bool home;
|
bool home;
|
||||||
|
|
||||||
struct Weapon {
|
struct Weapon {
|
||||||
enum Type { EMPTY, PISTOLS, SHOTGUN, MAGNUMS, UZIS, MAX };
|
enum Type { EMPTY = -1, PISTOLS, SHOTGUN, MAGNUMS, UZIS, MAX };
|
||||||
enum State { IS_HIDDEN, IS_ARMED, IS_FIRING };
|
enum State { IS_HIDDEN, IS_ARMED, IS_FIRING };
|
||||||
enum Anim { NONE, PREPARE, UNHOLSTER, HOLSTER, HOLD, AIM, FIRE };
|
enum Anim { NONE, PREPARE, UNHOLSTER, HOLSTER, HOLD, AIM, FIRE };
|
||||||
|
|
||||||
@@ -203,14 +203,16 @@ struct Lara : Character {
|
|||||||
int viewTarget;
|
int viewTarget;
|
||||||
|
|
||||||
Lara(TR::Level *level, int entity, bool home) : Character(level, entity, 1000), home(home), wpnCurrent(Weapon::EMPTY), wpnNext(Weapon::EMPTY), chestOffset(pos), viewTarget(-1) {
|
Lara(TR::Level *level, int entity, bool home) : Character(level, entity, 1000), home(home), wpnCurrent(Weapon::EMPTY), wpnNext(Weapon::EMPTY), chestOffset(pos), viewTarget(-1) {
|
||||||
animation.setAnim(ANIM_STAND);
|
|
||||||
|
if (getEntity().type == TR::Entity::LARA) {
|
||||||
|
if (getRoom().flags.water)
|
||||||
|
animation.setAnim(ANIM_UNDERWATER);
|
||||||
|
else
|
||||||
|
animation.setAnim(ANIM_STAND);
|
||||||
|
}
|
||||||
|
|
||||||
getEntity().flags.active = 1;
|
getEntity().flags.active = 1;
|
||||||
initMeshOverrides();
|
initMeshOverrides();
|
||||||
for (int i = 0; i < 2; i++) {
|
|
||||||
arms[i].shotTimer = MUZZLE_FLASH_TIME + 1.0f;
|
|
||||||
arms[i].rot = quat(0, 0, 0, 1);
|
|
||||||
arms[i].rotAbs = quat(0, 0, 0, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(weapons, -1, sizeof(weapons));
|
memset(weapons, -1, sizeof(weapons));
|
||||||
if (!home) {
|
if (!home) {
|
||||||
@@ -221,6 +223,13 @@ struct Lara : Character {
|
|||||||
wpnSet(Weapon::PISTOLS);
|
wpnSet(Weapon::PISTOLS);
|
||||||
} else
|
} else
|
||||||
meshSwap(1, TR::MODEL_LARA_SPEC, BODY_UPPER | BODY_LOWER);
|
meshSwap(1, TR::MODEL_LARA_SPEC, BODY_UPPER | BODY_LOWER);
|
||||||
|
|
||||||
|
for (int i = 0; i < 2; i++) {
|
||||||
|
arms[i].shotTimer = MUZZLE_FLASH_TIME + 1.0f;
|
||||||
|
arms[i].rot = quat(0, 0, 0, 1);
|
||||||
|
arms[i].rotAbs = quat(0, 0, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
/*
|
/*
|
||||||
// gym
|
// gym
|
||||||
@@ -301,8 +310,6 @@ struct Lara : Character {
|
|||||||
updateEntity();
|
updateEntity();
|
||||||
#endif
|
#endif
|
||||||
chestOffset = animation.getJoints(getMatrix(), 7).pos;
|
chestOffset = animation.getJoints(getMatrix(), 7).pos;
|
||||||
if (getRoom().flags.water)
|
|
||||||
animation.setAnim(ANIM_UNDERWATER);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void wpnSet(Weapon::Type wType) {
|
void wpnSet(Weapon::Type wType) {
|
||||||
@@ -346,7 +353,7 @@ struct Lara : Character {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void wpnSetState(Weapon::State wState) {
|
void wpnSetState(Weapon::State wState) {
|
||||||
if (wpnState == wState) return;
|
if (wpnState == wState || !layers) return;
|
||||||
|
|
||||||
int mask = 0;
|
int mask = 0;
|
||||||
switch (wpnCurrent) {
|
switch (wpnCurrent) {
|
||||||
@@ -381,15 +388,15 @@ struct Lara : Character {
|
|||||||
|
|
||||||
// swap weapon parts
|
// swap weapon parts
|
||||||
if (wpnCurrent != Weapon::SHOTGUN) {
|
if (wpnCurrent != Weapon::SHOTGUN) {
|
||||||
meshSwap(1, wpnCurrent, mask);
|
meshSwap(1, level->extra.weapons[wpnCurrent], mask);
|
||||||
// have a shotgun in inventory place it on the back if another weapon is in use
|
// have a shotgun in inventory place it on the back if another weapon is in use
|
||||||
meshSwap(2, Weapon::SHOTGUN, (weapons[Weapon::SHOTGUN].ammo != -1) ? BODY_CHEST : 0);
|
meshSwap(2, level->extra.weapons[Weapon::SHOTGUN], (weapons[Weapon::SHOTGUN].ammo != -1) ? BODY_CHEST : 0);
|
||||||
} else {
|
} else {
|
||||||
meshSwap(2, wpnCurrent, mask);
|
meshSwap(2, level->extra.weapons[wpnCurrent], mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
// mesh swap to angry Lara's head while firing (from uzis model)
|
// mesh swap to angry Lara's head while firing (from uzis model)
|
||||||
meshSwap(3, Weapon::UZIS, (wState == Weapon::IS_FIRING) ? BODY_HEAD : 0);
|
meshSwap(3, level->extra.weapons[Weapon::UZIS], (wState == Weapon::IS_FIRING) ? BODY_HEAD : 0);
|
||||||
|
|
||||||
wpnState = wState;
|
wpnState = wState;
|
||||||
}
|
}
|
||||||
@@ -872,6 +879,23 @@ struct Lara : Character {
|
|||||||
wpnHide();
|
wpnHide();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void drawGun(int right) {
|
||||||
|
int mask = right ? BODY_ARM_R3 : BODY_ARM_L3; // unholster
|
||||||
|
if (layers[1].mask & mask)
|
||||||
|
mask = right ? BODY_LEG_R1 : BODY_LEG_L1; // holster
|
||||||
|
meshSwap(1, level->extra.weapons[wpnCurrent], mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void cmdEffect(int fx) {
|
||||||
|
|
||||||
|
switch (fx) {
|
||||||
|
case TR::EFFECT_LARA_HANDSFREE : meshSwap(1, level->extra.weapons[wpnCurrent], BODY_LEG_L1 | BODY_LEG_R1); break;
|
||||||
|
case TR::EFFECT_DRAW_RIGHTGUN :
|
||||||
|
case TR::EFFECT_DRAW_LEFTGUN : drawGun(fx == TR::EFFECT_DRAW_RIGHTGUN); break;
|
||||||
|
default : LOG("unknown effect command %d (anim %d)\n", fx, animation.index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
virtual void hit(int damage, Controller *enemy = NULL) {
|
virtual void hit(int damage, Controller *enemy = NULL) {
|
||||||
health -= damage;
|
health -= damage;
|
||||||
if (enemy && health > 0)
|
if (enemy && health > 0)
|
||||||
@@ -1577,6 +1601,20 @@ struct Lara : Character {
|
|||||||
|
|
||||||
if (velocity.length() >= 0.001f)
|
if (velocity.length() >= 0.001f)
|
||||||
move();
|
move();
|
||||||
|
|
||||||
|
if (getEntity().type != TR::Entity::LARA) {
|
||||||
|
TR::Entity &e = getEntity();
|
||||||
|
vec3 &p = getPos();
|
||||||
|
e.x = int(p.x);
|
||||||
|
e.y = int(p.y);
|
||||||
|
e.z = int(p.z);
|
||||||
|
checkRoom();
|
||||||
|
updateEntity();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual vec3& getPos() {
|
||||||
|
return getEntity().type == TR::Entity::LARA ? pos : chestOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
void move() {
|
void move() {
|
||||||
|
@@ -669,7 +669,7 @@ struct Level {
|
|||||||
setRoomParams(room, isModel ? controller->specular : intensityf(lum));
|
setRoomParams(room, isModel ? controller->specular : intensityf(lum));
|
||||||
|
|
||||||
if (isModel) { // model
|
if (isModel) { // model
|
||||||
vec3 pos = controller->pos;
|
vec3 pos = controller->getPos();
|
||||||
AmbientCache::Cube cube;
|
AmbientCache::Cube cube;
|
||||||
if (Core::frameIndex != controller->frameIndex) {
|
if (Core::frameIndex != controller->frameIndex) {
|
||||||
ambientCache->getAmbient(entity.room, pos, cube);
|
ambientCache->getAmbient(entity.room, pos, cube);
|
||||||
@@ -875,8 +875,8 @@ struct Level {
|
|||||||
if (Input::down[ikM]) {
|
if (Input::down[ikM]) {
|
||||||
if (!lastStateK) {
|
if (!lastStateK) {
|
||||||
lastStateK = true;
|
lastStateK = true;
|
||||||
// modelIndex = (modelIndex + 1) % level.modelsCount;
|
modelIndex = (modelIndex + 1) % level.modelsCount;
|
||||||
modelIndex = (modelIndex + 1) % level.spriteSequencesCount;
|
// modelIndex = (modelIndex + 1) % level.spriteSequencesCount;
|
||||||
LOG("model: %d %d\n", modelIndex, level.spriteSequences[modelIndex].type);
|
LOG("model: %d %d\n", modelIndex, level.spriteSequences[modelIndex].type);
|
||||||
if (lastEntity > -1) {
|
if (lastEntity > -1) {
|
||||||
delete level.entities[lastEntity].controller;
|
delete level.entities[lastEntity].controller;
|
||||||
@@ -912,7 +912,8 @@ struct Level {
|
|||||||
glColor3f(1, 1, 1);
|
glColor3f(1, 1, 1);
|
||||||
for (int j = 0; j < 6; j++) {
|
for (int j = 0; j < 6; j++) {
|
||||||
glPushMatrix();
|
glPushMatrix();
|
||||||
glTranslatef(lara->pos.x, lara->pos.y - 1024, lara->pos.z);
|
vec3 p = lara->getPos();
|
||||||
|
glTranslatef(p.x, p.y - 1024, p.z);
|
||||||
switch (j) {
|
switch (j) {
|
||||||
case 0 : glRotatef( 90, 0, 1, 0); break;
|
case 0 : glRotatef( 90, 0, 1, 0); break;
|
||||||
case 1 : glRotatef(-90, 0, 1, 0); break;
|
case 1 : glRotatef(-90, 0, 1, 0); break;
|
||||||
|
Reference in New Issue
Block a user