mirror of
https://github.com/XProger/OpenLara.git
synced 2025-01-17 21:09:00 +01:00
#368 GBA mesh visible mask, enemies head/neck rotation, death animation for Wolf, Bear and Bat
This commit is contained in:
parent
e9ba3a2784
commit
6139aa4490
@ -9,6 +9,7 @@ int32 matrixStackIndex = 0;
|
||||
|
||||
const FloorData* gLastFloorData;
|
||||
FloorData gLastFloorSlant;
|
||||
TargetInfo tinfo;
|
||||
|
||||
EWRAM_DATA SaveGame gSaveGame;
|
||||
EWRAM_DATA Settings gSettings;
|
||||
|
@ -640,6 +640,14 @@ struct Room {
|
||||
Room** getVisibleRooms();
|
||||
};
|
||||
|
||||
enum NodeFlag {
|
||||
NODE_FLAG_POP = (1 << 0),
|
||||
NODE_FLAG_PUSH = (1 << 1),
|
||||
NODE_FLAG_ROTX = (1 << 2),
|
||||
NODE_FLAG_ROTY = (1 << 3),
|
||||
NODE_FLAG_ROTZ = (1 << 4),
|
||||
};
|
||||
|
||||
struct Node {
|
||||
uint16 flags;
|
||||
vec3s pos;
|
||||
@ -1159,24 +1167,29 @@ struct Item {
|
||||
uint16 frameIndex;
|
||||
|
||||
uint8 state;
|
||||
uint8 nextState;
|
||||
uint8 nextState; // enemies only
|
||||
uint8 goalState;
|
||||
uint8 waterState;
|
||||
|
||||
int16 headOffset; // enemies only
|
||||
int16 aggression;
|
||||
|
||||
int16 health;
|
||||
union {
|
||||
int16 timer;
|
||||
int16 oxygen;
|
||||
int16 oxygen; // Lara only
|
||||
int16 radius; // enemies only
|
||||
};
|
||||
|
||||
uint16 input;
|
||||
uint16 input; // Lara only
|
||||
int16 turnSpeed;
|
||||
|
||||
uint8 type;
|
||||
uint8 intensity;
|
||||
int16 roomFloor;
|
||||
|
||||
int32 hitMask;
|
||||
uint32 hitMask;
|
||||
uint32 visibleMask;
|
||||
|
||||
union {
|
||||
uint8* extra;
|
||||
@ -1606,6 +1619,17 @@ struct Level {
|
||||
const int32* soundOffsets;
|
||||
};
|
||||
|
||||
// used by enemies
|
||||
struct TargetInfo
|
||||
{
|
||||
Item* target;
|
||||
int16 angle;
|
||||
int16 rotHead;
|
||||
bool aim;
|
||||
};
|
||||
|
||||
extern TargetInfo tinfo;
|
||||
|
||||
extern Level level;
|
||||
|
||||
struct IMA_STATE {
|
||||
|
@ -103,7 +103,7 @@ void drawNumber(int32 number, int32 x, int32 y)
|
||||
}
|
||||
}
|
||||
|
||||
void drawMesh(int16 meshIndex)
|
||||
void drawMesh(int32 meshIndex)
|
||||
{
|
||||
const uint8* ptr = (uint8*)meshes[meshIndex] + sizeof(Mesh);
|
||||
|
||||
@ -224,22 +224,41 @@ void drawNodes(const Item* item, const AnimFrame* frameA)
|
||||
{
|
||||
const Model* model = models + item->type;
|
||||
const Node* node = level.nodes + model->nodeIndex;
|
||||
int32 meshIndex = model->start;
|
||||
int32 meshCount = model->count;
|
||||
uint32 visibleMask = item->visibleMask;
|
||||
|
||||
const uint32* angles = (uint32*)(frameA->angles + 1);
|
||||
const int16* extraAngles = (int16*)item->extra;
|
||||
|
||||
matrixFrame(frameA->pos, angles);
|
||||
if (visibleMask & 1) {
|
||||
drawMesh(meshIndex);
|
||||
}
|
||||
|
||||
drawMesh(model->start);
|
||||
|
||||
for (int32 i = 1; i < model->count; i++)
|
||||
while (meshCount > 1)
|
||||
{
|
||||
if (node->flags & 1) matrixPop();
|
||||
if (node->flags & 2) matrixPush();
|
||||
meshIndex++;
|
||||
visibleMask >>= 1;
|
||||
angles++;
|
||||
|
||||
matrixFrame(node->pos, ++angles);
|
||||
if (node->flags & NODE_FLAG_POP) matrixPop();
|
||||
if (node->flags & NODE_FLAG_PUSH) matrixPush();
|
||||
|
||||
drawMesh(model->start + i);
|
||||
matrixFrame(node->pos, angles);
|
||||
|
||||
if (extraAngles)
|
||||
{
|
||||
if (node->flags & NODE_FLAG_ROTY) matrixRotateY(*extraAngles++);
|
||||
if (node->flags & NODE_FLAG_ROTX) matrixRotateX(*extraAngles++);
|
||||
if (node->flags & NODE_FLAG_ROTZ) matrixRotateZ(*extraAngles++);
|
||||
}
|
||||
|
||||
if (visibleMask & 1) {
|
||||
drawMesh(meshIndex);
|
||||
}
|
||||
|
||||
meshCount--;
|
||||
node++;
|
||||
}
|
||||
}
|
||||
@ -254,9 +273,13 @@ void drawNodesLerp(const Item* item, const AnimFrame* frameA, const AnimFrame* f
|
||||
|
||||
const Model* model = models + item->type;
|
||||
const Node* node = level.nodes + model->nodeIndex;
|
||||
int32 meshIndex = model->start;
|
||||
int32 meshCount = model->count;
|
||||
uint32 visibleMask = item->visibleMask;
|
||||
|
||||
const uint32* anglesA = (uint32*)(frameA->angles + 1);
|
||||
const uint32* anglesB = (uint32*)(frameB->angles + 1);
|
||||
const int16* extraAngles = (int16*)item->extra;
|
||||
|
||||
int32 t = FixedInvU(frameRate) * frameDelta;
|
||||
|
||||
@ -266,18 +289,34 @@ void drawNodesLerp(const Item* item, const AnimFrame* frameA, const AnimFrame* f
|
||||
posLerp.z = frameA->pos.z + ((frameB->pos.z - frameA->pos.z) * t >> 16);
|
||||
|
||||
matrixFrameLerp(posLerp, anglesA, anglesB, frameDelta, frameRate);
|
||||
if (visibleMask & 1) {
|
||||
drawMesh(meshIndex);
|
||||
}
|
||||
|
||||
drawMesh(model->start);
|
||||
|
||||
for (int32 i = 1; i < model->count; i++)
|
||||
while (meshCount > 1)
|
||||
{
|
||||
if (node->flags & 1) matrixPop();
|
||||
if (node->flags & 2) matrixPush();
|
||||
meshIndex++;
|
||||
visibleMask >>= 1;
|
||||
anglesA++;
|
||||
anglesB++;
|
||||
|
||||
matrixFrameLerp(node->pos, ++anglesA, ++anglesB, frameDelta, frameRate);
|
||||
if (node->flags & NODE_FLAG_POP) matrixPop();
|
||||
if (node->flags & NODE_FLAG_PUSH) matrixPush();
|
||||
|
||||
drawMesh(model->start + i);
|
||||
matrixFrameLerp(node->pos, anglesA, anglesB, frameDelta, frameRate);
|
||||
|
||||
if (extraAngles)
|
||||
{
|
||||
if (node->flags & NODE_FLAG_ROTY) matrixRotateY(*extraAngles++);
|
||||
if (node->flags & NODE_FLAG_ROTX) matrixRotateX(*extraAngles++);
|
||||
if (node->flags & NODE_FLAG_ROTZ) matrixRotateZ(*extraAngles++);
|
||||
}
|
||||
|
||||
if (visibleMask & 1) {
|
||||
drawMesh(meshIndex);
|
||||
}
|
||||
|
||||
meshCount--;
|
||||
node++;
|
||||
}
|
||||
}
|
||||
|
@ -1,13 +1,22 @@
|
||||
#ifndef H_ENEMY
|
||||
#define H_ENEMY
|
||||
|
||||
#include "common.h"
|
||||
#include "item.h"
|
||||
|
||||
EWRAM_DATA ExtraInfoEnemy enemiesExtra[MAX_ENEMIES];
|
||||
|
||||
enum AggressionLevel
|
||||
{
|
||||
AGGRESSION_LVL_1 = 0x400,
|
||||
AGGRESSION_LVL_2 = 0x2000,
|
||||
AGGRESSION_LVL_3 = 0x4000,
|
||||
AGGRESSION_LVL_MAX = 0x7FFF,
|
||||
};
|
||||
|
||||
struct Enemy : Item
|
||||
{
|
||||
Enemy(Room* room, int32 hp) : Item(room)
|
||||
Enemy(Room* room, int32 _health, int32 _radius, int32 _headOffset, uint32 _aggression) : Item(room)
|
||||
{
|
||||
flags.shadow = true;
|
||||
|
||||
@ -15,7 +24,10 @@ struct Enemy : Item
|
||||
angle.y += (rand_logic() - 0x4000) >> 1;
|
||||
#endif
|
||||
|
||||
health = hp;
|
||||
health = _health;
|
||||
radius = _radius;
|
||||
headOffset = _headOffset;
|
||||
aggression = _aggression;
|
||||
}
|
||||
|
||||
void setExtra(ExtraInfoEnemy* extra)
|
||||
@ -99,6 +111,31 @@ struct Enemy : Item
|
||||
extraE = NULL;
|
||||
}
|
||||
|
||||
void updateTargetInfo()
|
||||
{
|
||||
tinfo.target = getLara(pos);
|
||||
|
||||
if (health <= 0)
|
||||
{
|
||||
tinfo.angle = 0;
|
||||
tinfo.rotHead = 0;
|
||||
tinfo.aim = false;
|
||||
return;
|
||||
}
|
||||
|
||||
int32 dx = tinfo.target->pos.x - pos.x;
|
||||
int32 dz = tinfo.target->pos.z - pos.z;
|
||||
|
||||
if (headOffset) {
|
||||
dx -= phd_sin(angle.y) * headOffset >> FIXED_SHIFT;
|
||||
dz -= phd_cos(angle.y) * headOffset >> FIXED_SHIFT;
|
||||
}
|
||||
|
||||
tinfo.angle = phd_atan(dz, dx) - angle.y;
|
||||
tinfo.aim = (tinfo.angle > -ANGLE_90) && (tinfo.angle < ANGLE_90);
|
||||
tinfo.rotHead = tinfo.aim ? tinfo.angle : 0;
|
||||
}
|
||||
|
||||
virtual void activate()
|
||||
{
|
||||
Item::activate();
|
||||
@ -110,31 +147,26 @@ struct Enemy : Item
|
||||
|
||||
virtual void hit(int32 damage, const vec3i &point, int32 soundId)
|
||||
{
|
||||
if (health > 0) {
|
||||
health -= damage;
|
||||
ASSERT(health > 0);
|
||||
|
||||
if (health <= 0) {
|
||||
gSaveGame.kills++;
|
||||
}
|
||||
}
|
||||
health -= damage;
|
||||
|
||||
if (health > 0)
|
||||
{
|
||||
if (type != ITEM_MUMMY) {
|
||||
fxBlood(point, 0, 0);
|
||||
}
|
||||
|
||||
if (soundId) {
|
||||
soundPlay(soundId, pos);
|
||||
}
|
||||
} else {
|
||||
gSaveGame.kills++;
|
||||
}
|
||||
|
||||
if (type != ITEM_MUMMY) {
|
||||
fxBlood(point, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void collide(Lara* lara, CollisionInfo* cinfo)
|
||||
{
|
||||
if (health <= 0) // TODO T-Rex still collide after death
|
||||
return;
|
||||
|
||||
if (!extraE) // disabled
|
||||
return;
|
||||
|
||||
@ -159,11 +191,29 @@ struct Enemy : Item
|
||||
flags.status = ITEM_FLAGS_STATUS_ACTIVE;
|
||||
}
|
||||
|
||||
if (extraE) {
|
||||
logic();
|
||||
}
|
||||
if (!extraE)
|
||||
return;
|
||||
|
||||
updateTargetInfo();
|
||||
|
||||
logic();
|
||||
|
||||
extraE->rotHead = angleLerp(extraE->rotHead, tinfo.rotHead, ANGLE(5));
|
||||
|
||||
animProcess();
|
||||
|
||||
if (flags.status == ITEM_FLAGS_STATUS_INACTIVE)
|
||||
{
|
||||
flags.collision = false;
|
||||
health = NOT_ENEMY;
|
||||
disable();
|
||||
deactivate();
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO collision, pathfinding
|
||||
|
||||
updateRoom();
|
||||
}
|
||||
|
||||
virtual void logic() {}
|
||||
@ -172,51 +222,166 @@ struct Enemy : Item
|
||||
|
||||
struct Doppelganger : Enemy
|
||||
{
|
||||
Doppelganger(Room* room) : Enemy(room, LARA_MAX_HEALTH) {}
|
||||
Doppelganger(Room* room) : Enemy(room, LARA_MAX_HEALTH, 10, 0, 0) {}
|
||||
};
|
||||
|
||||
|
||||
struct Wolf : Enemy
|
||||
{
|
||||
Wolf(Room* room) : Enemy(room, 6) {}
|
||||
enum {
|
||||
HIT_MASK = 0x774F, // body, head, front legs
|
||||
};
|
||||
|
||||
enum {
|
||||
ANIM_DEATH = 20,
|
||||
ANIM_DEATH_RUN,
|
||||
ANIM_DEATH_JUMP,
|
||||
};
|
||||
|
||||
enum {
|
||||
STATE_NONE,
|
||||
STATE_STOP,
|
||||
STATE_WALK,
|
||||
STATE_RUN,
|
||||
STATE_JUMP, // unused
|
||||
STATE_STALK,
|
||||
STATE_ATTACK,
|
||||
STATE_HOWL,
|
||||
STATE_SLEEP,
|
||||
STATE_GROWL,
|
||||
STATE_TURN, // unused
|
||||
STATE_DEATH,
|
||||
STATE_BITE,
|
||||
};
|
||||
|
||||
Wolf(Room* room) : Enemy(room, 6, 341, 375, AGGRESSION_LVL_2)
|
||||
{
|
||||
frameIndex = level.anims[animIndex].frameEnd;
|
||||
}
|
||||
|
||||
virtual void hit(int32 damage, const vec3i &point, int32 soundId)
|
||||
{
|
||||
Enemy::hit(damage, point, SND_HIT_WOLF);
|
||||
|
||||
if (health <= 0) {
|
||||
animSet(models[type].animIndex + ANIM_DEATH + (rand_logic() % 3), true);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void logic()
|
||||
{
|
||||
if (health <= 0)
|
||||
return;
|
||||
|
||||
// TODO
|
||||
|
||||
if (state == STATE_SLEEP) {
|
||||
goalState = STATE_STOP;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct Bear : Enemy
|
||||
{
|
||||
Bear(Room* room) : Enemy(room, 20) {}
|
||||
enum {
|
||||
HIT_MASK = 0x2406C, // front legs and head
|
||||
};
|
||||
|
||||
enum {
|
||||
STATE_WALK,
|
||||
STATE_STOP,
|
||||
STATE_HIND,
|
||||
STATE_RUN,
|
||||
STATE_STAND,
|
||||
STATE_GROWL,
|
||||
STATE_BITE,
|
||||
STATE_ATTACK,
|
||||
STATE_EAT,
|
||||
STATE_DEATH,
|
||||
};
|
||||
|
||||
Bear(Room* room) : Enemy(room, 20, 341, 500, AGGRESSION_LVL_3) {}
|
||||
|
||||
virtual void hit(int32 damage, const vec3i &point, int32 soundId)
|
||||
{
|
||||
Enemy::hit(damage, point, SND_HIT_BEAR);
|
||||
}
|
||||
|
||||
virtual void logic()
|
||||
{
|
||||
if (health <= 0)
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case STATE_HIND:
|
||||
goalState = STATE_STAND;
|
||||
break;
|
||||
case STATE_WALK:
|
||||
case STATE_RUN:
|
||||
goalState = STATE_STOP;
|
||||
break;
|
||||
case STATE_STOP:
|
||||
case STATE_STAND:
|
||||
goalState = STATE_DEATH;
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct Bat : Enemy
|
||||
{
|
||||
Bat(Room* room) : Enemy(room, 1) {}
|
||||
enum {
|
||||
STATE_NONE,
|
||||
STATE_AWAKE,
|
||||
STATE_FLY,
|
||||
STATE_ATTACK,
|
||||
STATE_CIRCLING,
|
||||
STATE_DEATH,
|
||||
};
|
||||
|
||||
Bat(Room* room) : Enemy(room, 1, 102, 0, AGGRESSION_LVL_1) {}
|
||||
|
||||
virtual void logic()
|
||||
{
|
||||
if (health <= 0)
|
||||
{
|
||||
hSpeed = 0;
|
||||
flags.gravity = (pos.y < roomFloor);
|
||||
|
||||
if (flags.gravity) {
|
||||
goalState = STATE_CIRCLING;
|
||||
} else {
|
||||
goalState = STATE_DEATH;
|
||||
pos.y = roomFloor;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct Crocodile : Enemy
|
||||
{
|
||||
Crocodile(Room* room) : Enemy(room, 20) {}
|
||||
Crocodile(Room* room) : Enemy(room, 20, 341, 600, AGGRESSION_LVL_2) {}
|
||||
};
|
||||
|
||||
|
||||
struct Lion : Enemy
|
||||
{
|
||||
Lion(Room* room) : Enemy(room, 1)
|
||||
Lion(Room* room) : Enemy(room, 1, 341, 400, AGGRESSION_LVL_2)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case ITEM_LION_MALE : health = 30; break;
|
||||
case ITEM_LION_MALE : health = 30; aggression = AGGRESSION_LVL_MAX; break;
|
||||
case ITEM_LION_FEMALE : health = 25; break;
|
||||
case ITEM_PUMA : health = 40; break;
|
||||
}
|
||||
@ -231,13 +396,13 @@ struct Lion : Enemy
|
||||
|
||||
struct Gorilla : Enemy
|
||||
{
|
||||
Gorilla(Room* room) : Enemy(room, 22) {}
|
||||
Gorilla(Room* room) : Enemy(room, 22, 341, 250, AGGRESSION_LVL_MAX) {}
|
||||
};
|
||||
|
||||
|
||||
struct Rat : Enemy
|
||||
{
|
||||
Rat(Room* room) : Enemy(room, 5) {}
|
||||
Rat(Room* room) : Enemy(room, 5, 204, 200, AGGRESSION_LVL_2) {}
|
||||
|
||||
virtual void hit(int32 damage, const vec3i &point, int32 soundId)
|
||||
{
|
||||
@ -248,49 +413,49 @@ struct Rat : Enemy
|
||||
|
||||
struct Rex : Enemy
|
||||
{
|
||||
Rex(Room* room) : Enemy(room, 100) {}
|
||||
Rex(Room* room) : Enemy(room, 100, 341, 2000, AGGRESSION_LVL_MAX) {}
|
||||
};
|
||||
|
||||
|
||||
struct Raptor : Enemy
|
||||
{
|
||||
Raptor(Room* room) : Enemy(room, 20) {}
|
||||
Raptor(Room* room) : Enemy(room, 20, 341, 400, AGGRESSION_LVL_3) {}
|
||||
};
|
||||
|
||||
|
||||
struct Mutant : Enemy
|
||||
{
|
||||
Mutant(Room* room) : Enemy(room, 50) {}
|
||||
Mutant(Room* room) : Enemy(room, 50, 341, 150, AGGRESSION_LVL_MAX) {}
|
||||
};
|
||||
|
||||
|
||||
struct Centaur : Enemy
|
||||
{
|
||||
Centaur(Room* room) : Enemy(room, 120) {}
|
||||
Centaur(Room* room) : Enemy(room, 120, 341, 400, AGGRESSION_LVL_MAX) {}
|
||||
};
|
||||
|
||||
|
||||
struct Mummy : Enemy
|
||||
{
|
||||
Mummy(Room* room) : Enemy(room, 18) {}
|
||||
Mummy(Room* room) : Enemy(room, 18, 10, 0, AGGRESSION_LVL_MAX) {}
|
||||
};
|
||||
|
||||
|
||||
struct Larson : Enemy
|
||||
{
|
||||
Larson(Room* room) : Enemy(room, 50) {}
|
||||
Larson(Room* room) : Enemy(room, 50, 102, 0, AGGRESSION_LVL_MAX) {}
|
||||
};
|
||||
|
||||
|
||||
struct Pierre : Enemy
|
||||
{
|
||||
Pierre(Room* room) : Enemy(room, 70) {}
|
||||
Pierre(Room* room) : Enemy(room, 70, 102, 0, AGGRESSION_LVL_MAX) {}
|
||||
};
|
||||
|
||||
|
||||
struct Skater : Enemy
|
||||
{
|
||||
Skater(Room* room) : Enemy(room, 125) {}
|
||||
Skater(Room* room) : Enemy(room, 125, 204, 0, AGGRESSION_LVL_MAX) {}
|
||||
|
||||
virtual void hit(int32 damage, const vec3i &point, int32 soundId)
|
||||
{
|
||||
@ -301,25 +466,25 @@ struct Skater : Enemy
|
||||
|
||||
struct Cowboy : Enemy
|
||||
{
|
||||
Cowboy(Room* room) : Enemy(room, 150) {}
|
||||
Cowboy(Room* room) : Enemy(room, 150, 102, 0, AGGRESSION_LVL_MAX) {}
|
||||
};
|
||||
|
||||
|
||||
struct MrT : Enemy
|
||||
{
|
||||
MrT(Room* room) : Enemy(room, 200) {}
|
||||
MrT(Room* room) : Enemy(room, 200, 102, 0, AGGRESSION_LVL_MAX) {}
|
||||
};
|
||||
|
||||
|
||||
struct Natla : Enemy
|
||||
{
|
||||
Natla(Room* room) : Enemy(room, 400) {}
|
||||
Natla(Room* room) : Enemy(room, 400, 204, 0, AGGRESSION_LVL_MAX) {}
|
||||
};
|
||||
|
||||
|
||||
struct Adam : Enemy
|
||||
{
|
||||
Adam(Room* room) : Enemy(room, 500) {}
|
||||
Adam(Room* room) : Enemy(room, 500, 341, 0, AGGRESSION_LVL_MAX) {}
|
||||
|
||||
virtual void hit(int32 damage, const vec3i &point, int32 soundId)
|
||||
{
|
||||
|
@ -967,6 +967,8 @@ Item::Item(Room* room)
|
||||
goalState = state;
|
||||
extra = NULL;
|
||||
health = NOT_ENEMY;
|
||||
hitMask = 0;
|
||||
visibleMask = 0xFFFFFFFF;
|
||||
|
||||
flags.save = true;
|
||||
flags.gravity = false;
|
||||
|
@ -3073,7 +3073,7 @@ struct Lara : Item
|
||||
|
||||
int32 minDist = INT_MAX;
|
||||
|
||||
if (arm->target)
|
||||
if (arm->target && arm->target->health > 0)
|
||||
{
|
||||
Sphere spheres[MAX_SPHERES];
|
||||
int32 spheresCount = arm->target->getSpheres(spheres, false);
|
||||
|
@ -18,6 +18,209 @@ typedef unsigned long long uint64;
|
||||
#define MIN(a,b) ((a) < (b) ? (a) : (b))
|
||||
#define MAX(a,b) ((a) > (b) ? (a) : (b))
|
||||
|
||||
#define ITEM_TYPES(E) \
|
||||
E( LARA ) \
|
||||
E( LARA_PISTOLS ) \
|
||||
E( LARA_SHOTGUN ) \
|
||||
E( LARA_MAGNUMS ) \
|
||||
E( LARA_UZIS ) \
|
||||
E( LARA_SPEC ) \
|
||||
E( DOPPELGANGER ) \
|
||||
E( WOLF ) \
|
||||
E( BEAR ) \
|
||||
E( BAT ) \
|
||||
E( CROCODILE_LAND ) \
|
||||
E( CROCODILE_WATER ) \
|
||||
E( LION_MALE ) \
|
||||
E( LION_FEMALE ) \
|
||||
E( PUMA ) \
|
||||
E( GORILLA ) \
|
||||
E( RAT_LAND ) \
|
||||
E( RAT_WATER ) \
|
||||
E( REX ) \
|
||||
E( RAPTOR ) \
|
||||
E( MUTANT_1 ) \
|
||||
E( MUTANT_2 ) \
|
||||
E( MUTANT_3 ) \
|
||||
E( CENTAUR ) \
|
||||
E( MUMMY ) \
|
||||
E( UNUSED_1 ) \
|
||||
E( UNUSED_2 ) \
|
||||
E( LARSON ) \
|
||||
E( PIERRE ) \
|
||||
E( SKATEBOARD ) \
|
||||
E( SKATER ) \
|
||||
E( COWBOY ) \
|
||||
E( MR_T ) \
|
||||
E( NATLA ) \
|
||||
E( ADAM ) \
|
||||
E( TRAP_FLOOR ) \
|
||||
E( TRAP_SWING_BLADE ) \
|
||||
E( TRAP_SPIKES ) \
|
||||
E( TRAP_BOULDER ) \
|
||||
E( DART ) \
|
||||
E( TRAP_DART_EMITTER ) \
|
||||
E( DRAWBRIDGE ) \
|
||||
E( TRAP_SLAM ) \
|
||||
E( TRAP_SWORD ) \
|
||||
E( HAMMER_HANDLE ) \
|
||||
E( HAMMER_BLOCK ) \
|
||||
E( LIGHTNING ) \
|
||||
E( MOVING_OBJECT ) \
|
||||
E( BLOCK_1 ) \
|
||||
E( BLOCK_2 ) \
|
||||
E( BLOCK_3 ) \
|
||||
E( BLOCK_4 ) \
|
||||
E( MOVING_BLOCK ) \
|
||||
E( TRAP_CEILING ) \
|
||||
E( UNUSED_3 ) \
|
||||
E( SWITCH ) \
|
||||
E( SWITCH_WATER ) \
|
||||
E( DOOR_1 ) \
|
||||
E( DOOR_2 ) \
|
||||
E( DOOR_3 ) \
|
||||
E( DOOR_4 ) \
|
||||
E( DOOR_5 ) \
|
||||
E( DOOR_6 ) \
|
||||
E( DOOR_7 ) \
|
||||
E( DOOR_8 ) \
|
||||
E( TRAP_DOOR_1 ) \
|
||||
E( TRAP_DOOR_2 ) \
|
||||
E( UNUSED_4 ) \
|
||||
E( BRIDGE_FLAT ) \
|
||||
E( BRIDGE_TILT_1 ) \
|
||||
E( BRIDGE_TILT_2 ) \
|
||||
E( INV_PASSPORT ) \
|
||||
E( INV_COMPASS ) \
|
||||
E( INV_HOME ) \
|
||||
E( GEARS_1 ) \
|
||||
E( GEARS_2 ) \
|
||||
E( GEARS_3 ) \
|
||||
E( CUT_1 ) \
|
||||
E( CUT_2 ) \
|
||||
E( CUT_3 ) \
|
||||
E( CUT_4 ) \
|
||||
E( INV_PASSPORT_CLOSED ) \
|
||||
E( INV_MAP ) \
|
||||
E( CRYSTAL ) \
|
||||
E( PISTOLS ) \
|
||||
E( SHOTGUN ) \
|
||||
E( MAGNUMS ) \
|
||||
E( UZIS ) \
|
||||
E( AMMO_PISTOLS ) \
|
||||
E( AMMO_SHOTGUN ) \
|
||||
E( AMMO_MAGNUMS ) \
|
||||
E( AMMO_UZIS ) \
|
||||
E( EXPLOSIVE ) \
|
||||
E( MEDIKIT_SMALL ) \
|
||||
E( MEDIKIT_BIG ) \
|
||||
E( INV_DETAIL ) \
|
||||
E( INV_SOUND ) \
|
||||
E( INV_CONTROLS ) \
|
||||
E( INV_GAMMA ) \
|
||||
E( INV_PISTOLS ) \
|
||||
E( INV_SHOTGUN ) \
|
||||
E( INV_MAGNUMS ) \
|
||||
E( INV_UZIS ) \
|
||||
E( INV_AMMO_PISTOLS ) \
|
||||
E( INV_AMMO_SHOTGUN ) \
|
||||
E( INV_AMMO_MAGNUMS ) \
|
||||
E( INV_AMMO_UZIS ) \
|
||||
E( INV_EXPLOSIVE ) \
|
||||
E( INV_MEDIKIT_SMALL ) \
|
||||
E( INV_MEDIKIT_BIG ) \
|
||||
E( PUZZLE_1 ) \
|
||||
E( PUZZLE_2 ) \
|
||||
E( PUZZLE_3 ) \
|
||||
E( PUZZLE_4 ) \
|
||||
E( INV_PUZZLE_1 ) \
|
||||
E( INV_PUZZLE_2 ) \
|
||||
E( INV_PUZZLE_3 ) \
|
||||
E( INV_PUZZLE_4 ) \
|
||||
E( PUZZLEHOLE_1 ) \
|
||||
E( PUZZLEHOLE_2 ) \
|
||||
E( PUZZLEHOLE_3 ) \
|
||||
E( PUZZLEHOLE_4 ) \
|
||||
E( PUZZLEHOLE_DONE_1 ) \
|
||||
E( PUZZLEHOLE_DONE_2 ) \
|
||||
E( PUZZLEHOLE_DONE_3 ) \
|
||||
E( PUZZLEHOLE_DONE_4 ) \
|
||||
E( LEADBAR ) \
|
||||
E( INV_LEADBAR ) \
|
||||
E( MIDAS_HAND ) \
|
||||
E( KEY_ITEM_1 ) \
|
||||
E( KEY_ITEM_2 ) \
|
||||
E( KEY_ITEM_3 ) \
|
||||
E( KEY_ITEM_4 ) \
|
||||
E( INV_KEY_ITEM_1 ) \
|
||||
E( INV_KEY_ITEM_2 ) \
|
||||
E( INV_KEY_ITEM_3 ) \
|
||||
E( INV_KEY_ITEM_4 ) \
|
||||
E( KEYHOLE_1 ) \
|
||||
E( KEYHOLE_2 ) \
|
||||
E( KEYHOLE_3 ) \
|
||||
E( KEYHOLE_4 ) \
|
||||
E( UNUSED_5 ) \
|
||||
E( UNUSED_6 ) \
|
||||
E( SCION_PICKUP_QUALOPEC ) \
|
||||
E( SCION_PICKUP_DROP ) \
|
||||
E( SCION_TARGET ) \
|
||||
E( SCION_PICKUP_HOLDER ) \
|
||||
E( SCION_HOLDER ) \
|
||||
E( UNUSED_7 ) \
|
||||
E( UNUSED_8 ) \
|
||||
E( INV_SCION ) \
|
||||
E( EXPLOSION ) \
|
||||
E( UNUSED_9 ) \
|
||||
E( SPLASH ) \
|
||||
E( UNUSED_10 ) \
|
||||
E( BUBBLE ) \
|
||||
E( UNUSED_11 ) \
|
||||
E( UNUSED_12 ) \
|
||||
E( BLOOD ) \
|
||||
E( UNUSED_13 ) \
|
||||
E( SMOKE ) \
|
||||
E( CENTAUR_STATUE ) \
|
||||
E( CABIN ) \
|
||||
E( MUTANT_EGG_SMALL ) \
|
||||
E( RICOCHET ) \
|
||||
E( SPARKLES ) \
|
||||
E( MUZZLE_FLASH ) \
|
||||
E( UNUSED_14 ) \
|
||||
E( UNUSED_15 ) \
|
||||
E( VIEW_TARGET ) \
|
||||
E( WATERFALL ) \
|
||||
E( NATLA_BULLET ) \
|
||||
E( MUTANT_BULLET ) \
|
||||
E( CENTAUR_BULLET ) \
|
||||
E( UNUSED_16 ) \
|
||||
E( UNUSED_17 ) \
|
||||
E( LAVA_PARTICLE ) \
|
||||
E( LAVA_EMITTER ) \
|
||||
E( FLAME ) \
|
||||
E( FLAME_EMITTER ) \
|
||||
E( TRAP_LAVA ) \
|
||||
E( MUTANT_EGG_BIG ) \
|
||||
E( BOAT ) \
|
||||
E( EARTHQUAKE ) \
|
||||
E( UNUSED_18 ) \
|
||||
E( UNUSED_19 ) \
|
||||
E( UNUSED_20 ) \
|
||||
E( UNUSED_21 ) \
|
||||
E( UNUSED_22 ) \
|
||||
E( LARA_BRAID ) \
|
||||
E( GLYPHS )
|
||||
|
||||
#define DECL_ENUM(v) ITEM_##v,
|
||||
|
||||
enum ItemType {
|
||||
ITEM_TYPES(DECL_ENUM)
|
||||
TR1_ITEM_MAX,
|
||||
ITEM_MAX = TR1_ITEM_MAX
|
||||
};
|
||||
|
||||
#undef DECL_ENUM
|
||||
|
||||
struct vec3s
|
||||
{
|
||||
int16 x, y, z;
|
||||
@ -722,6 +925,15 @@ struct LevelPC
|
||||
uint16 flags;
|
||||
};
|
||||
|
||||
enum NodeFlag
|
||||
{
|
||||
NODE_FLAG_POP = (1 << 0),
|
||||
NODE_FLAG_PUSH = (1 << 1),
|
||||
NODE_FLAG_ROTX = (1 << 2),
|
||||
NODE_FLAG_ROTY = (1 << 3),
|
||||
NODE_FLAG_ROTZ = (1 << 4),
|
||||
};
|
||||
|
||||
struct Node
|
||||
{
|
||||
uint32 flags;
|
||||
@ -1108,6 +1320,46 @@ struct LevelPC
|
||||
*/
|
||||
}
|
||||
|
||||
void fixHeadMask()
|
||||
{
|
||||
#define SET_ROT(joint, mask) (((Node*)nodesData)[models[i].nodeIndex / 4 + joint]).flags |= mask;
|
||||
|
||||
for (int32 i = 0; i < modelsCount; i++)
|
||||
{
|
||||
switch (models[i].type)
|
||||
{
|
||||
case ITEM_WOLF : SET_ROT(2, NODE_FLAG_ROTY); break;
|
||||
case ITEM_BEAR : SET_ROT(13, NODE_FLAG_ROTY); break;
|
||||
//case ITEM_BAT : break;
|
||||
case ITEM_CROCODILE_LAND : SET_ROT(7, NODE_FLAG_ROTY); break;
|
||||
case ITEM_CROCODILE_WATER : SET_ROT(7, NODE_FLAG_ROTY); break;
|
||||
case ITEM_LION_MALE : SET_ROT(19, NODE_FLAG_ROTY); break;
|
||||
case ITEM_LION_FEMALE : SET_ROT(19, NODE_FLAG_ROTY); break;
|
||||
case ITEM_PUMA : SET_ROT(19, NODE_FLAG_ROTY); break;
|
||||
case ITEM_GORILLA : SET_ROT(13, NODE_FLAG_ROTY); break;
|
||||
case ITEM_RAT_LAND : SET_ROT(1, NODE_FLAG_ROTY); break;
|
||||
case ITEM_RAT_WATER : SET_ROT(1, NODE_FLAG_ROTY); break;
|
||||
case ITEM_REX : SET_ROT(10, NODE_FLAG_ROTY); SET_ROT(11, NODE_FLAG_ROTY); break;
|
||||
case ITEM_RAPTOR : SET_ROT(21, NODE_FLAG_ROTY); break;
|
||||
case ITEM_MUTANT_1 : SET_ROT(0, NODE_FLAG_ROTY); SET_ROT(2, NODE_FLAG_ROTY); break;
|
||||
case ITEM_MUTANT_2 : SET_ROT(0, NODE_FLAG_ROTY); SET_ROT(2, NODE_FLAG_ROTY); break;
|
||||
case ITEM_MUTANT_3 : SET_ROT(0, NODE_FLAG_ROTY); SET_ROT(2, NODE_FLAG_ROTY); break;
|
||||
case ITEM_CENTAUR : SET_ROT(10, NODE_FLAG_ROTX | NODE_FLAG_ROTY); break;
|
||||
case ITEM_MUMMY : SET_ROT(2, NODE_FLAG_ROTY); break;
|
||||
case ITEM_LARSON : SET_ROT(6, NODE_FLAG_ROTY); break;
|
||||
case ITEM_PIERRE : SET_ROT(6, NODE_FLAG_ROTY); break;
|
||||
case ITEM_SKATER : SET_ROT(0, NODE_FLAG_ROTY); break;
|
||||
case ITEM_COWBOY : SET_ROT(0, NODE_FLAG_ROTY); break;
|
||||
case ITEM_MR_T : SET_ROT(0, NODE_FLAG_ROTY); break;
|
||||
case ITEM_NATLA : SET_ROT(2, NODE_FLAG_ROTX | NODE_FLAG_ROTZ); break;
|
||||
case ITEM_ADAM : SET_ROT(1, NODE_FLAG_ROTY); break;
|
||||
default : break;
|
||||
}
|
||||
}
|
||||
|
||||
#undef SET_ROT
|
||||
}
|
||||
|
||||
void convertGBA(const char* fileName)
|
||||
{
|
||||
FileStream f(fileName, true);
|
||||
@ -1156,6 +1408,8 @@ struct LevelPC
|
||||
lightmap[i * 256] = 0;
|
||||
}
|
||||
|
||||
fixHeadMask();
|
||||
|
||||
header.lightmap = f.align4();
|
||||
f.write(lightmap);
|
||||
|
||||
@ -2396,8 +2650,7 @@ void pack_tracks(const char* dir)
|
||||
|
||||
int main()
|
||||
{
|
||||
pack_tracks("tracks/conv_demo/*.ima");
|
||||
return 0;
|
||||
//pack_tracks("tracks/conv_demo/*.ima"); return 0;
|
||||
|
||||
for (int32 i = 0; i < MAX_LEVELS; i++)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user