1
0
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:
XProger 2021-08-02 05:08:21 +03:00
parent e9ba3a2784
commit 6139aa4490
7 changed files with 545 additions and 61 deletions

View File

@ -9,6 +9,7 @@ int32 matrixStackIndex = 0;
const FloorData* gLastFloorData;
FloorData gLastFloorSlant;
TargetInfo tinfo;
EWRAM_DATA SaveGame gSaveGame;
EWRAM_DATA Settings gSettings;

View File

@ -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 {

View File

@ -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++;
}
}

View File

@ -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)
{

View File

@ -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;

View File

@ -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);

View File

@ -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++)
{