mirror of
https://github.com/halpz/re3.git
synced 2025-06-29 09:56:25 +00:00
first commit
This commit is contained in:
117
src/modelinfo/BaseModelInfo.cpp
Normal file
117
src/modelinfo/BaseModelInfo.cpp
Normal file
@ -0,0 +1,117 @@
|
||||
#include "common.h"
|
||||
#include "patcher.h"
|
||||
#include "templates.h"
|
||||
#include "TxdStore.h"
|
||||
#include "2dEffect.h"
|
||||
#include "BaseModelInfo.h"
|
||||
|
||||
|
||||
CBaseModelInfo::CBaseModelInfo(ModeInfoType type)
|
||||
{
|
||||
m_colModel = nil;
|
||||
m_twodEffects = 0;
|
||||
m_objectId = -1;
|
||||
m_refCount = 0;
|
||||
m_txdSlot = -1;
|
||||
m_type = type;
|
||||
m_num2dEffects = 0;
|
||||
m_freeCol = false;
|
||||
}
|
||||
|
||||
void
|
||||
CBaseModelInfo::Shutdown(void)
|
||||
{
|
||||
DeleteCollisionModel();
|
||||
DeleteRwObject();
|
||||
m_twodEffects = 0;
|
||||
m_num2dEffects = 0;
|
||||
m_txdSlot = -1;
|
||||
}
|
||||
|
||||
void
|
||||
CBaseModelInfo::DeleteCollisionModel(void)
|
||||
{
|
||||
if(m_colModel && m_freeCol){
|
||||
if(m_colModel)
|
||||
delete m_colModel;
|
||||
m_colModel = nil;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CBaseModelInfo::AddRef(void)
|
||||
{
|
||||
m_refCount++;
|
||||
AddTexDictionaryRef();
|
||||
}
|
||||
|
||||
void
|
||||
CBaseModelInfo::RemoveRef(void)
|
||||
{
|
||||
m_refCount--;
|
||||
RemoveTexDictionaryRef();
|
||||
}
|
||||
|
||||
void
|
||||
CBaseModelInfo::SetTexDictionary(const char *name)
|
||||
{
|
||||
int slot = CTxdStore::FindTxdSlot(name);
|
||||
if(slot < 0)
|
||||
slot = CTxdStore::AddTxdSlot(name);
|
||||
m_txdSlot = slot;
|
||||
}
|
||||
|
||||
void
|
||||
CBaseModelInfo::AddTexDictionaryRef(void)
|
||||
{
|
||||
CTxdStore::AddRef(m_txdSlot);
|
||||
}
|
||||
|
||||
void
|
||||
CBaseModelInfo::RemoveTexDictionaryRef(void)
|
||||
{
|
||||
CTxdStore::RemoveRef(m_txdSlot);
|
||||
}
|
||||
|
||||
void
|
||||
CBaseModelInfo::Init2dEffects(void)
|
||||
{
|
||||
m_twodEffects = nil;
|
||||
m_num2dEffects = 0;
|
||||
}
|
||||
|
||||
void
|
||||
CBaseModelInfo::Add2dEffect(C2dEffect *fx)
|
||||
{
|
||||
if(m_twodEffects)
|
||||
m_num2dEffects++;
|
||||
else{
|
||||
m_twodEffects = fx;
|
||||
m_num2dEffects = 1;
|
||||
}
|
||||
}
|
||||
|
||||
C2dEffect*
|
||||
CBaseModelInfo::Get2dEffect(int n)
|
||||
{
|
||||
if(m_twodEffects)
|
||||
return &m_twodEffects[n];
|
||||
else
|
||||
return nil;
|
||||
}
|
||||
|
||||
|
||||
STARTPATCHES
|
||||
// can't easily replace ctor at 4F6A50
|
||||
InjectHook(0x4F6A90, &CBaseModelInfo::Shutdown_, PATCH_JUMP);
|
||||
InjectHook(0x4F6AC0, &CBaseModelInfo::DeleteCollisionModel, PATCH_JUMP);
|
||||
InjectHook(0x4F6B70, &CBaseModelInfo::ClearTexDictionary, PATCH_JUMP);
|
||||
InjectHook(0x4F6BA0, &CBaseModelInfo::AddRef, PATCH_JUMP);
|
||||
InjectHook(0x4F6BB0, &CBaseModelInfo::RemoveRef, PATCH_JUMP);
|
||||
InjectHook(0x4F6B40, &CBaseModelInfo::SetTexDictionary, PATCH_JUMP);
|
||||
InjectHook(0x4F6B80, &CBaseModelInfo::AddTexDictionaryRef, PATCH_JUMP);
|
||||
InjectHook(0x4F6B90, &CBaseModelInfo::RemoveTexDictionaryRef, PATCH_JUMP);
|
||||
InjectHook(0x4F6B20, &CBaseModelInfo::Add2dEffect, PATCH_JUMP);
|
||||
InjectHook(0x4F6AF0, &CBaseModelInfo::Init2dEffects, PATCH_JUMP);
|
||||
InjectHook(0x4F6B00, &CBaseModelInfo::Get2dEffect, PATCH_JUMP);
|
||||
ENDPATCHES
|
66
src/modelinfo/BaseModelInfo.h
Normal file
66
src/modelinfo/BaseModelInfo.h
Normal file
@ -0,0 +1,66 @@
|
||||
#pragma once
|
||||
|
||||
#include "Collision.h"
|
||||
|
||||
enum ModeInfoType : uint8
|
||||
{
|
||||
MITYPE_NA = 0,
|
||||
MITYPE_SIMPLE = 1,
|
||||
MITYPE_MLO = 2,
|
||||
MITYPE_TIME = 3,
|
||||
MITYPE_CLUMP = 4,
|
||||
MITYPE_VEHICLE = 5,
|
||||
MITYPE_PED = 6,
|
||||
MITYPE_XTRACOMPS = 7,
|
||||
};
|
||||
static_assert(sizeof(ModeInfoType) == 1, "ModeInfoType: error");
|
||||
|
||||
class C2dEffect;
|
||||
|
||||
class CBaseModelInfo
|
||||
{
|
||||
protected:
|
||||
// TODO?: make more things protected
|
||||
char m_name[24];
|
||||
CColModel *m_colModel;
|
||||
C2dEffect *m_twodEffects;
|
||||
int16 m_objectId;
|
||||
public:
|
||||
uint16 m_refCount;
|
||||
int16 m_txdSlot;
|
||||
ModeInfoType m_type;
|
||||
uint8 m_num2dEffects;
|
||||
bool m_freeCol;
|
||||
|
||||
CBaseModelInfo(ModeInfoType type);
|
||||
virtual ~CBaseModelInfo() {}
|
||||
virtual void Shutdown(void);
|
||||
virtual void DeleteRwObject(void) = 0;
|
||||
virtual RwObject *CreateInstance(RwMatrix *) = 0;
|
||||
virtual RwObject *CreateInstance(void) = 0;
|
||||
virtual RwObject *GetRwObject(void) = 0;
|
||||
|
||||
bool IsSimple(void) { return m_type == MITYPE_SIMPLE || m_type == MITYPE_TIME; }
|
||||
char *GetName(void) { return m_name; }
|
||||
void SetName(const char *name) { strncpy(m_name, name, 24); }
|
||||
void SetColModel(CColModel *col, bool free = false){
|
||||
m_colModel = col; m_freeCol = free; }
|
||||
CColModel *GetColModel(void) { return m_colModel; }
|
||||
void DeleteCollisionModel(void);
|
||||
void ClearTexDictionary(void) { m_txdSlot = -1; }
|
||||
short GetObjectID(void) { return m_objectId; }
|
||||
void SetObjectID(short id) { m_objectId = id; }
|
||||
short GetTxdSlot(void) { return m_txdSlot; }
|
||||
void AddRef(void);
|
||||
void RemoveRef(void);
|
||||
void SetTexDictionary(const char *name);
|
||||
void AddTexDictionaryRef(void);
|
||||
void RemoveTexDictionaryRef(void);
|
||||
void Init2dEffects(void);
|
||||
void Add2dEffect(C2dEffect *fx);
|
||||
C2dEffect *Get2dEffect(int n);
|
||||
|
||||
void Shutdown_(void) { this->CBaseModelInfo::Shutdown(); }
|
||||
};
|
||||
|
||||
static_assert(sizeof(CBaseModelInfo) == 0x30, "CBaseModelInfo: error");
|
156
src/modelinfo/ClumpModelInfo.cpp
Normal file
156
src/modelinfo/ClumpModelInfo.cpp
Normal file
@ -0,0 +1,156 @@
|
||||
#include "common.h"
|
||||
#include "patcher.h"
|
||||
#include "NodeName.h"
|
||||
#include "VisibilityPlugins.h"
|
||||
#include "ModelInfo.h"
|
||||
|
||||
void
|
||||
CClumpModelInfo::DeleteRwObject(void)
|
||||
{
|
||||
if(m_clump){
|
||||
RpClumpDestroy(m_clump);
|
||||
m_clump = nil;
|
||||
RemoveTexDictionaryRef();
|
||||
}
|
||||
}
|
||||
|
||||
RwObject*
|
||||
CClumpModelInfo::CreateInstance(void)
|
||||
{
|
||||
if(m_clump)
|
||||
return (RwObject*)RpClumpClone(m_clump);
|
||||
return nil;
|
||||
}
|
||||
|
||||
RwObject*
|
||||
CClumpModelInfo::CreateInstance(RwMatrix *m)
|
||||
{
|
||||
if(m_clump){
|
||||
RpClump *clump = (RpClump*)CreateInstance();
|
||||
*RwFrameGetMatrix(RpClumpGetFrame(clump)) = *m;
|
||||
return (RwObject*)clump;
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
RpAtomic*
|
||||
CClumpModelInfo::SetAtomicRendererCB(RpAtomic *atomic, void *data)
|
||||
{
|
||||
CVisibilityPlugins::SetAtomicRenderCallback(atomic, (RpAtomicCallBackRender)data);
|
||||
return atomic;
|
||||
}
|
||||
|
||||
void
|
||||
CClumpModelInfo::SetClump(RpClump *clump)
|
||||
{
|
||||
m_clump = clump;
|
||||
CVisibilityPlugins::SetClumpModelInfo(m_clump, this);
|
||||
AddTexDictionaryRef();
|
||||
RpClumpForAllAtomics(clump, SetAtomicRendererCB, nil);
|
||||
if(strncmp(GetName(), "playerh", 8) == 0)
|
||||
RpClumpForAllAtomics(clump, SetAtomicRendererCB, CVisibilityPlugins::RenderPlayerCB);
|
||||
}
|
||||
|
||||
void
|
||||
CClumpModelInfo::SetFrameIds(RwObjectNameIdAssocation *assocs)
|
||||
{
|
||||
int32 i;
|
||||
RwObjectNameAssociation objname;
|
||||
|
||||
for(i = 0; assocs[i].name; i++)
|
||||
if((assocs[i].flags & CLUMP_FLAG_NO_HIERID) == 0){
|
||||
objname.frame = nil;
|
||||
objname.name = assocs[i].name;
|
||||
RwFrameForAllChildren(RpClumpGetFrame(m_clump), FindFrameFromNameWithoutIdCB, &objname);
|
||||
if(objname.frame)
|
||||
CVisibilityPlugins::SetFrameHierarchyId(objname.frame, assocs[i].hierId);
|
||||
}
|
||||
}
|
||||
|
||||
RwFrame*
|
||||
CClumpModelInfo::FindFrameFromIdCB(RwFrame *frame, void *data)
|
||||
{
|
||||
RwObjectIdAssociation *assoc = (RwObjectIdAssociation*)data;
|
||||
|
||||
if(CVisibilityPlugins::GetFrameHierarchyId(frame) != assoc->id){
|
||||
RwFrameForAllChildren(frame, FindFrameFromIdCB, assoc);
|
||||
return assoc->frame ? nil : frame;
|
||||
}else{
|
||||
assoc->frame = frame;
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
|
||||
RwFrame*
|
||||
CClumpModelInfo::FindFrameFromNameCB(RwFrame *frame, void *data)
|
||||
{
|
||||
RwObjectNameAssociation *assoc = (RwObjectNameAssociation*)data;
|
||||
|
||||
if(_strcmpi(GetFrameNodeName(frame), assoc->name) != 0){
|
||||
RwFrameForAllChildren(frame, FindFrameFromNameCB, assoc);
|
||||
return assoc->frame ? nil : frame;
|
||||
}else{
|
||||
assoc->frame = frame;
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
|
||||
RwFrame*
|
||||
CClumpModelInfo::FindFrameFromNameWithoutIdCB(RwFrame *frame, void *data)
|
||||
{
|
||||
RwObjectNameAssociation *assoc = (RwObjectNameAssociation*)data;
|
||||
|
||||
if(CVisibilityPlugins::GetFrameHierarchyId(frame) ||
|
||||
_strcmpi(GetFrameNodeName(frame), assoc->name) != 0){
|
||||
RwFrameForAllChildren(frame, FindFrameFromNameWithoutIdCB, assoc);
|
||||
return assoc->frame ? nil : frame;
|
||||
}else{
|
||||
assoc->frame = frame;
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
|
||||
RwFrame*
|
||||
CClumpModelInfo::FillFrameArrayCB(RwFrame *frame, void *data)
|
||||
{
|
||||
int32 id;
|
||||
RwFrame **frames = (RwFrame**)data;
|
||||
id = CVisibilityPlugins::GetFrameHierarchyId(frame);
|
||||
if(id > 0)
|
||||
frames[id] = frame;
|
||||
RwFrameForAllChildren(frame, FillFrameArrayCB, data);
|
||||
return frame;
|
||||
}
|
||||
|
||||
void
|
||||
CClumpModelInfo::FillFrameArray(RpClump *clump, RwFrame **frames)
|
||||
{
|
||||
RwFrameForAllChildren(RpClumpGetFrame(clump), FillFrameArrayCB, frames);
|
||||
}
|
||||
|
||||
RwFrame*
|
||||
CClumpModelInfo::GetFrameFromId(RpClump *clump, int32 id)
|
||||
{
|
||||
RwObjectIdAssociation assoc;
|
||||
assoc.id = id;
|
||||
assoc.frame = nil;
|
||||
RwFrameForAllChildren(RpClumpGetFrame(clump), FindFrameFromIdCB, &assoc);
|
||||
return assoc.frame;
|
||||
}
|
||||
|
||||
|
||||
STARTPATCHES
|
||||
InjectHook(0x4F8800, &CClumpModelInfo::DeleteRwObject_, PATCH_JUMP);
|
||||
InjectHook(0x4F8920, &CClumpModelInfo::CreateInstance_1, PATCH_JUMP);
|
||||
InjectHook(0x4F88A0, &CClumpModelInfo::CreateInstance_2, PATCH_JUMP);
|
||||
InjectHook(0x50C1C0, &CClumpModelInfo::GetRwObject_, PATCH_JUMP);
|
||||
InjectHook(0x4F8830, &CClumpModelInfo::SetClump_, PATCH_JUMP);
|
||||
InjectHook(0x4F8940, &CClumpModelInfo::SetAtomicRendererCB, PATCH_JUMP);
|
||||
InjectHook(0x4F8960, &CClumpModelInfo::FindFrameFromNameCB, PATCH_JUMP);
|
||||
InjectHook(0x4F8A10, &CClumpModelInfo::FindFrameFromNameWithoutIdCB, PATCH_JUMP);
|
||||
InjectHook(0x4F8AD0, &CClumpModelInfo::FindFrameFromIdCB, PATCH_JUMP);
|
||||
InjectHook(0x4F8BB0, &CClumpModelInfo::SetFrameIds, PATCH_JUMP);
|
||||
InjectHook(0x4F8B20, &CClumpModelInfo::FillFrameArrayCB, PATCH_JUMP);
|
||||
InjectHook(0x4F8B90, &CClumpModelInfo::FillFrameArray, PATCH_JUMP);
|
||||
InjectHook(0x4F8B50, &CClumpModelInfo::GetFrameFromId, PATCH_JUMP);
|
||||
ENDPATCHES
|
60
src/modelinfo/ClumpModelInfo.h
Normal file
60
src/modelinfo/ClumpModelInfo.h
Normal file
@ -0,0 +1,60 @@
|
||||
#pragma once
|
||||
|
||||
#include "BaseModelInfo.h"
|
||||
|
||||
struct RwObjectNameIdAssocation
|
||||
{
|
||||
char *name;
|
||||
int32 hierId;
|
||||
uint32 flags;
|
||||
};
|
||||
|
||||
struct RwObjectNameAssociation
|
||||
{
|
||||
char *name;
|
||||
RwFrame *frame;
|
||||
};
|
||||
|
||||
struct RwObjectIdAssociation
|
||||
{
|
||||
int32 id;
|
||||
RwFrame *frame;
|
||||
};
|
||||
|
||||
enum {
|
||||
CLUMP_FLAG_NO_HIERID = 0x1,
|
||||
};
|
||||
|
||||
|
||||
class CClumpModelInfo : public CBaseModelInfo
|
||||
{
|
||||
public:
|
||||
RpClump *m_clump;
|
||||
|
||||
CClumpModelInfo(void) : CBaseModelInfo(MITYPE_CLUMP) {}
|
||||
CClumpModelInfo(ModeInfoType id) : CBaseModelInfo(id) {}
|
||||
~CClumpModelInfo() {}
|
||||
void DeleteRwObject(void);
|
||||
RwObject *CreateInstance(void);
|
||||
RwObject *CreateInstance(RwMatrix *);
|
||||
RwObject *GetRwObject(void) { return (RwObject*)m_clump; }
|
||||
|
||||
virtual void SetClump(RpClump *);
|
||||
|
||||
static RpAtomic *SetAtomicRendererCB(RpAtomic *atomic, void *data);
|
||||
void SetFrameIds(RwObjectNameIdAssocation *assocs);
|
||||
static RwFrame *FindFrameFromNameCB(RwFrame *frame, void *data);
|
||||
static RwFrame *FindFrameFromNameWithoutIdCB(RwFrame *frame, void *data);
|
||||
static RwFrame *FindFrameFromIdCB(RwFrame *frame, void *data);
|
||||
static void FillFrameArray(RpClump *clump, RwFrame **frames);
|
||||
static RwFrame *FillFrameArrayCB(RwFrame *frame, void *data);
|
||||
static RwFrame *GetFrameFromId(RpClump *clump, int32 id);
|
||||
|
||||
|
||||
void DeleteRwObject_(void) { this->CClumpModelInfo::DeleteRwObject(); }
|
||||
RwObject *CreateInstance_1(void) { return this->CClumpModelInfo::CreateInstance(); }
|
||||
RwObject *CreateInstance_2(RwMatrix *m) { return this->CClumpModelInfo::CreateInstance(m); }
|
||||
RwObject *GetRwObject_(void) { return this->CClumpModelInfo::GetRwObject(); }
|
||||
void SetClump_(RpClump *clump) { this->CClumpModelInfo::SetClump(clump); }
|
||||
};
|
||||
static_assert(sizeof(CClumpModelInfo) == 0x34, "CClumpModelInfo: error");
|
32
src/modelinfo/ModelIndices.cpp
Normal file
32
src/modelinfo/ModelIndices.cpp
Normal file
@ -0,0 +1,32 @@
|
||||
#include "common.h"
|
||||
#include "patcher.h"
|
||||
#include "ModelIndices.h"
|
||||
|
||||
#define X(name, var, addr) int16 &var = *(int16*)addr;
|
||||
MODELINDICES
|
||||
#undef X
|
||||
|
||||
void
|
||||
InitModelIndices(void)
|
||||
{
|
||||
#define X(name, var, addr) var = -1;
|
||||
MODELINDICES
|
||||
#undef X
|
||||
}
|
||||
|
||||
void
|
||||
MatchModelString(const char *modelname, int16 id)
|
||||
{
|
||||
#define X(name, var, addr) \
|
||||
if(strcmp(name, modelname) == 0){ \
|
||||
var = id; \
|
||||
return; \
|
||||
}
|
||||
MODELINDICES
|
||||
#undef X
|
||||
}
|
||||
|
||||
STARTPATCHES
|
||||
InjectHook(0x48EB60, InitModelIndices, PATCH_JUMP);
|
||||
InjectHook(0x48F030, MatchModelString, PATCH_JUMP);
|
||||
ENDPATCHES
|
224
src/modelinfo/ModelIndices.h
Normal file
224
src/modelinfo/ModelIndices.h
Normal file
@ -0,0 +1,224 @@
|
||||
#define MODELINDICES \
|
||||
X("fire_hydrant", MI_FIRE_HYDRANT, 0x5F5A00) \
|
||||
X("bagelstnd02", MI_BAGELSTAND2, 0x5F59FC) \
|
||||
X("fish01", MI_FISHSTALL01, 0x5F59EC) \
|
||||
X("fishstall02", MI_FISHSTALL02, 0x5F59F0) \
|
||||
X("fishstall03", MI_FISHSTALL03, 0x5F59F4) \
|
||||
X("fishstall04", MI_FISHSTALL04, 0x5F59F8) \
|
||||
X("taxisign", MI_TAXISIGN, 0x5F59E8) \
|
||||
X("phonesign", MI_PHONESIGN, 0x5F59E4) \
|
||||
X("noparkingsign1", MI_NOPARKINGSIGN1, 0x5F59E0) \
|
||||
X("bussign1", MI_BUSSIGN1, 0x5F59DC) \
|
||||
X("roadworkbarrier1", MI_ROADWORKBARRIER1, 0x5F59D8) \
|
||||
X("dump1", MI_DUMP1, 0x5F59D4) \
|
||||
X("trafficcone", MI_TRAFFICCONE, 0x5F59D0) \
|
||||
X("newsstand1", MI_NEWSSTAND, 0x5F59CC) \
|
||||
X("postbox1", MI_POSTBOX1, 0x5F59C8) \
|
||||
X("bin1", MI_BIN, 0x5F59C4) \
|
||||
X("wastebin", MI_WASTEBIN, 0x5F59C0) \
|
||||
X("phonebooth1", MI_PHONEBOOTH1, 0x5F59BC) \
|
||||
X("parkingmeter", MI_PARKINGMETER, 0x5F59B8) \
|
||||
X("trafficlight1", MI_TRAFFICLIGHTS, 0x5F5958) \
|
||||
X("lamppost1", MI_SINGLESTREETLIGHTS1, 0x5F595C) \
|
||||
X("lamppost2", MI_SINGLESTREETLIGHTS2, 0x5F5960) \
|
||||
X("lamppost3", MI_SINGLESTREETLIGHTS3, 0x5F5964) \
|
||||
X("doublestreetlght1", MI_DOUBLESTREETLIGHTS, 0x5F5968) \
|
||||
X("rd_Road2A10", MI_ROADSFORROADBLOCKSSTART, 0x5F596C) \
|
||||
X("rd_Road1A30", MI_ROADSFORROADBLOCKSEND, 0x5F5970) \
|
||||
X("veg_tree1", MI_TREE1, 0x5F5974) \
|
||||
X("veg_tree3", MI_TREE2, 0x5F5978) \
|
||||
X("veg_treea1", MI_TREE3, 0x5F597C) \
|
||||
X("veg_treenew01", MI_TREE4, 0x5F5980) \
|
||||
X("veg_treenew05", MI_TREE5, 0x5F5984) \
|
||||
X("veg_treeb1", MI_TREE6, 0x5F5988) \
|
||||
X("veg_treenew10", MI_TREE7, 0x5F598C) \
|
||||
X("veg_treea3", MI_TREE8, 0x5F5990) \
|
||||
X("veg_treenew09", MI_TREE9, 0x5F5994) \
|
||||
X("veg_treenew08", MI_TREE10, 0x5F5998) \
|
||||
X("veg_treenew03", MI_TREE11, 0x5F599C) \
|
||||
X("veg_treenew16", MI_TREE12, 0x5F59A0) \
|
||||
X("veg_treenew17", MI_TREE13, 0x5F59A4) \
|
||||
X("veg_treenew06", MI_TREE14, 0x5F59A8) \
|
||||
X("doc_crane_cab", MODELID_CRANE_1, 0x5F59AC) \
|
||||
X("cranetopb", MODELID_CRANE_2, 0x5F59B0) \
|
||||
X("cranetopa", MODELID_CRANE_3, 0x5F59B4) \
|
||||
X("package1", MI_COLLECTABLE1, 0x5F5A04) \
|
||||
X("Money", MI_MONEY, 0x5F5A08) \
|
||||
X("barrel1", MI_CARMINE, 0x5F5A0C) \
|
||||
X("oddjgaragdoor", MI_GARAGEDOOR1, 0x5F5A10) \
|
||||
X("bombdoor", MI_GARAGEDOOR2, 0x5F5A14) \
|
||||
X("door_bombshop", MI_GARAGEDOOR3, 0x5F5A18) \
|
||||
X("vheistlocdoor", MI_GARAGEDOOR4, 0x5F5A1C) \
|
||||
X("door2_garage", MI_GARAGEDOOR5, 0x5F5A20) \
|
||||
X("ind_slidedoor", MI_GARAGEDOOR6, 0x5F5A24) \
|
||||
X("bankjobdoor", MI_GARAGEDOOR7, 0x5F5A28) \
|
||||
X("door_jmsgrage", MI_GARAGEDOOR9, 0x5F5A2C) \
|
||||
X("jamesgrge_kb", MI_GARAGEDOOR10, 0x5F5A30) \
|
||||
X("door_sfehousegrge", MI_GARAGEDOOR11, 0x5F5A34) \
|
||||
X("shedgaragedoor", MI_GARAGEDOOR12, 0x5F5A38) \
|
||||
X("door4_garage", MI_GARAGEDOOR13, 0x5F5A3C) \
|
||||
X("door_col_compnd_01", MI_GARAGEDOOR14, 0x5F5A40) \
|
||||
X("door_col_compnd_02", MI_GARAGEDOOR15, 0x5F5A44) \
|
||||
X("door_col_compnd_03", MI_GARAGEDOOR16, 0x5F5A48) \
|
||||
X("door_col_compnd_04", MI_GARAGEDOOR17, 0x5F5A4C) \
|
||||
X("door_col_compnd_05", MI_GARAGEDOOR18, 0x5F5A50) \
|
||||
X("impex_door", MI_GARAGEDOOR19, 0x5F5A54) \
|
||||
X("SalvGarage", MI_GARAGEDOOR20, 0x5F5A58) \
|
||||
X("door3_garage", MI_GARAGEDOOR21, 0x5F5A5C) \
|
||||
X("leveldoor2", MI_GARAGEDOOR22, 0x5F5A60) \
|
||||
X("double_garage_dr", MI_GARAGEDOOR23, 0x5F5A64) \
|
||||
X("amcogaragedoor", MI_GARAGEDOOR24, 0x5F5A68) \
|
||||
X("towergaragedoor1", MI_GARAGEDOOR25, 0x5F5A6C) \
|
||||
X("towergaragedoor2", MI_GARAGEDOOR26, 0x5F5A70) \
|
||||
X("towergaragedoor3", MI_GARAGEDOOR27, 0x5F5A74) \
|
||||
X("plysve_gragedoor", MI_GARAGEDOOR28, 0x5F5A78) \
|
||||
X("impexpsubgrgdoor", MI_GARAGEDOOR29, 0x5F5A7C) \
|
||||
X("Sub_sprayshopdoor", MI_GARAGEDOOR30, 0x5F5A80) \
|
||||
X("ind_plyrwoor", MI_GARAGEDOOR31, 0x5F5A84) \
|
||||
X("8ballsuburbandoor", MI_GARAGEDOOR32, 0x5F5A88) \
|
||||
X("barrel2", MI_NAUTICALMINE, 0x5F5A8C) \
|
||||
X("crushercrush", MI_CRUSHERBODY, 0x5F5A90) \
|
||||
X("crushertop", MI_CRUSHERLID, 0x5F5A94) \
|
||||
X("donkeymag", MI_DONKEYMAG, 0x5F5A98) \
|
||||
X("bullion", MI_BULLION, 0x5F5A9C) \
|
||||
X("floatpackge1", MI_FLOATPACKAGE1, 0x5F5AA0) \
|
||||
X("briefcase", MI_BRIEFCASE, 0x5F5AA4) \
|
||||
X("chinabanner1", MI_CHINABANNER1, 0x5F5AA8) \
|
||||
X("chinabanner2", MI_CHINABANNER2, 0x5F5AAC) \
|
||||
X("chinabanner3", MI_CHINABANNER3, 0x5F5AB0) \
|
||||
X("chinabanner4", MI_CHINABANNER4, 0x5F5AB4) \
|
||||
X("iten_chinatown5", MI_CHINABANNER5, 0x5F5AB8) \
|
||||
X("iten_chinatown7", MI_CHINABANNER6, 0x5F5ABC) \
|
||||
X("iten_chinatown3", MI_CHINABANNER7, 0x5F5AC0) \
|
||||
X("iten_chinatown2", MI_CHINABANNER8, 0x5F5AC4) \
|
||||
X("iten_chinatown4", MI_CHINABANNER9, 0x5F5AC8) \
|
||||
X("iten_washline01", MI_CHINABANNER10, 0x5F5ACC) \
|
||||
X("iten_washline02", MI_CHINABANNER11, 0x5F5AD0) \
|
||||
X("iten_washline03", MI_CHINABANNER12, 0x5F5AD4) \
|
||||
X("chinalanterns", MI_CHINALANTERN, 0x5F5AD8) \
|
||||
X("glassfx1", MI_GLASS1, 0x5F5ADC) \
|
||||
X("glassfx2", MI_GLASS2, 0x5F5AE0) \
|
||||
X("glassfx3", MI_GLASS3, 0x5F5AE4) \
|
||||
X("glassfx4", MI_GLASS4, 0x5F5AE8) \
|
||||
X("glassfx55", MI_GLASS5, 0x5F5AEC) \
|
||||
X("glassfxsub1", MI_GLASS6, 0x5F5AF0) \
|
||||
X("glassfxsub2", MI_GLASS7, 0x5F5AF4) \
|
||||
X("glassfx_composh", MI_GLASS8, 0x5F5AF8) \
|
||||
X("bridge_liftsec", MI_BRIDGELIFT, 0x5F5AFC) \
|
||||
X("bridge_liftweight", MI_BRIDGEWEIGHT, 0x5F5B00) \
|
||||
X("subbridge_lift", MI_BRIDGEROADSEGMENT, 0x5F5B04) \
|
||||
X("barrel4", MI_EXPLODINGBARREL, 0x5F5B08) \
|
||||
X("flagsitaly", MI_ITALYBANNER1, 0x5F5B0C) \
|
||||
X("adrenaline", MI_PICKUP_ADRENALINE, 0x5F5B10) \
|
||||
X("bodyarmour", MI_PICKUP_BODYARMOUR, 0x5F5B14) \
|
||||
X("info", MI_PICKUP_INFO, 0x5F5B18) \
|
||||
X("health", MI_PICKUP_HEALTH, 0x5F5B1C) \
|
||||
X("bonus", MI_PICKUP_BONUS, 0x5F5B20) \
|
||||
X("bribe", MI_PICKUP_BRIBE, 0x5F5B24) \
|
||||
X("killfrenzy", MI_PICKUP_KILLFRENZY, 0x5F5B28) \
|
||||
X("camerapickup", MI_PICKUP_CAMERA, 0x5F5B2C) \
|
||||
X("bollardlight", MI_BOLLARDLIGHT, 0x5F5B30) \
|
||||
X("magnet", MI_MAGNET, 0x5F5B34) \
|
||||
X("streetlamp1", MI_STREETLAMP1, 0x5F5B38) \
|
||||
X("streetlamp2", MI_STREETLAMP2, 0x5F5B3C) \
|
||||
X("railtrax_lo4b", MI_RAILTRACKS, 0x5F5B40) \
|
||||
X("bar_barrier10", MI_FENCE, 0x5F5B44) \
|
||||
X("bar_barrier12", MI_FENCE2, 0x5F5B48) \
|
||||
X("petrolpump", MI_PETROLPUMP, 0x5F5B4C) \
|
||||
X("bodycast", MI_BODYCAST, 0x5F5B50) \
|
||||
X("backdoor", MI_BACKDOOR, 0x5F5B54) \
|
||||
X("coffee", MI_COFFEE, 0x5F5B58) \
|
||||
X("bouy", MI_BUOY, 0x5F5B5C) \
|
||||
X("parktable1", MI_PARKTABLE, 0x5F5B60) \
|
||||
X("sbwy_tunl_start", MI_SUBWAY1, 0x5F5B64) \
|
||||
X("sbwy_tunl_bit", MI_SUBWAY2, 0x5F5B68) \
|
||||
X("sbwy_tunl_bend", MI_SUBWAY3, 0x5F5B6C) \
|
||||
X("sbwy_tunl_cstm6", MI_SUBWAY4, 0x5F5B70) \
|
||||
X("sbwy_tunl_cstm7", MI_SUBWAY5, 0x5F5B74) \
|
||||
X("sbwy_tunl_cstm8", MI_SUBWAY6, 0x5F5B78) \
|
||||
X("sbwy_tunl_cstm10", MI_SUBWAY7, 0x5F5B7C) \
|
||||
X("sbwy_tunl_cstm9", MI_SUBWAY8, 0x5F5B80) \
|
||||
X("sbwy_tunl_cstm11", MI_SUBWAY9, 0x5F5B84) \
|
||||
X("sbwy_tunl_cstm1", MI_SUBWAY10, 0x5F5B88) \
|
||||
X("sbwy_tunl_cstm2", MI_SUBWAY11, 0x5F5B8C) \
|
||||
X("sbwy_tunl_cstm4", MI_SUBWAY12, 0x5F5B90) \
|
||||
X("sbwy_tunl_cstm3", MI_SUBWAY13, 0x5F5B94) \
|
||||
X("sbwy_tunl_cstm5", MI_SUBWAY14, 0x5F5B98) \
|
||||
X("subplatform_n2", MI_SUBWAY15, 0x5F5B9C) \
|
||||
X("suby_tunl_start", MI_SUBWAY16, 0x5F5BA0) \
|
||||
X("sbwy_tunl_start2", MI_SUBWAY17, 0x5F5BA4) \
|
||||
X("indy_tunl_start", MI_SUBWAY18, 0x5F5BA8) \
|
||||
X("indsubway03", MI_SUBPLATFORM_IND, 0x5F5BAC) \
|
||||
X("comerside_subway", MI_SUBPLATFORM_COMS, 0x5F5BB0) \
|
||||
X("subplatform", MI_SUBPLATFORM_COMS2, 0x5F5BB4) \
|
||||
X("subplatform_n", MI_SUBPLATFORM_COMN, 0x5F5BB8) \
|
||||
X("Otherside_subway", MI_SUBPLATFORM_SUB, 0x5F5BBC) \
|
||||
X("subplatform_sub", MI_SUBPLATFORM_SUB2, 0x5F5BC0) \
|
||||
X("files", MI_FILES, 0x5F5BC4)
|
||||
|
||||
#define X(name, var, addr) extern int16 &var;
|
||||
MODELINDICES
|
||||
#undef X
|
||||
|
||||
// and some hardcoded ones
|
||||
// expand as needed
|
||||
enum
|
||||
{
|
||||
MI_COP = 1,
|
||||
MI_SWAT,
|
||||
MI_FBI,
|
||||
MI_ARMY,
|
||||
MI_MEDIC,
|
||||
MI_FIREMAN,
|
||||
MI_MALE01,
|
||||
MI_TAXI_D,
|
||||
MI_PIMP,
|
||||
MI_GANG01,
|
||||
MI_GANG02,
|
||||
MI_GANG03,
|
||||
MI_GANG04,
|
||||
MI_GANG05,
|
||||
MI_GANG06,
|
||||
MI_GANG07,
|
||||
MI_GANG08,
|
||||
MI_GANG09,
|
||||
MI_GANG10,
|
||||
MI_GANG11,
|
||||
MI_GANG12,
|
||||
MI_GANG13,
|
||||
MI_GANG14,
|
||||
MI_CRIMINAL01,
|
||||
MI_CRIMINAL02,
|
||||
MI_SPECIAL01,
|
||||
MI_SPECIAL02,
|
||||
MI_SPECIAL03,
|
||||
MI_SPECIAL04,
|
||||
MI_MALE02,
|
||||
MI_MALE03,
|
||||
MI_FATMALE01,
|
||||
MI_FATMALE02,
|
||||
MI_FEMALE01,
|
||||
MI_FEMALE02,
|
||||
MI_FEMALE03,
|
||||
MI_FATFEMALE01,
|
||||
MI_FATFEMALE02,
|
||||
|
||||
MI_RHINO = 122,
|
||||
MI_COACH = 127,
|
||||
};
|
||||
|
||||
void InitModelIndices(void);
|
||||
void MatchModelString(const char *name, int16 id);
|
||||
|
||||
inline bool
|
||||
IsGlass(int16 id)
|
||||
{
|
||||
return id == MI_GLASS1 ||
|
||||
id == MI_GLASS2 ||
|
||||
id == MI_GLASS3 ||
|
||||
id == MI_GLASS4 ||
|
||||
id == MI_GLASS5 ||
|
||||
id == MI_GLASS6 ||
|
||||
id == MI_GLASS7 ||
|
||||
id == MI_GLASS8;
|
||||
}
|
124
src/modelinfo/ModelInfo.cpp
Normal file
124
src/modelinfo/ModelInfo.cpp
Normal file
@ -0,0 +1,124 @@
|
||||
#include "common.h"
|
||||
#include "patcher.h"
|
||||
#include "ModelInfo.h"
|
||||
|
||||
CBaseModelInfo **CModelInfo::ms_modelInfoPtrs = (CBaseModelInfo**)0x83D408;
|
||||
|
||||
//CStore<CSimpleModelInfo, SIMPLEMODELSIZE> &CModelInfo::ms_simpleModelStore = *(CStore<CSimpleModelInfo, SIMPLEMODELSIZE>*)0x885BB4;
|
||||
//CStore<CTimeModelInfo, TIMEMODELSIZE> &CModelInfo::ms_timeModelStore = *(CStore<CTimeModelInfo, TIMEMODELSIZE>*)0x94076C;
|
||||
//CStore<C2dEffect, TWODFXSIZE> &CModelInfo::ms_2dEffectStore = *(CStore<C2dEffect, TWODFXSIZE>*)0x9434F8;
|
||||
CStore<CSimpleModelInfo, SIMPLEMODELSIZE> CModelInfo::ms_simpleModelStore;
|
||||
CStore<CTimeModelInfo, TIMEMODELSIZE> CModelInfo::ms_timeModelStore;
|
||||
CStore<CClumpModelInfo, CLUMPMODELSIZE> CModelInfo::ms_clumpModelStore;
|
||||
CStore<CPedModelInfo, PEDMODELSIZE> CModelInfo::ms_pedModelStore;
|
||||
CStore<CVehicleModelInfo, VEHICLEMODELSIZE> CModelInfo::ms_vehicleModelStore;
|
||||
CStore<C2dEffect, TWODFXSIZE> CModelInfo::ms_2dEffectStore;
|
||||
|
||||
void
|
||||
CModelInfo::Initialise(void)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < MODELINFOSIZE; i++)
|
||||
ms_modelInfoPtrs[i] = nil;
|
||||
ms_2dEffectStore.clear();
|
||||
ms_simpleModelStore.clear();
|
||||
ms_timeModelStore.clear();
|
||||
ms_clumpModelStore.clear();
|
||||
ms_pedModelStore.clear();
|
||||
ms_vehicleModelStore.clear();
|
||||
}
|
||||
|
||||
void
|
||||
CModelInfo::Shutdown(void)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < ms_simpleModelStore.allocPtr; i++)
|
||||
ms_simpleModelStore.store[i].Shutdown();
|
||||
for(i = 0; i < ms_timeModelStore.allocPtr; i++)
|
||||
ms_timeModelStore.store[i].Shutdown();
|
||||
for(i = 0; i < ms_clumpModelStore.allocPtr; i++)
|
||||
ms_clumpModelStore.store[i].Shutdown();
|
||||
for(i = 0; i < ms_pedModelStore.allocPtr; i++)
|
||||
ms_pedModelStore.store[i].Shutdown();
|
||||
for(i = 0; i < ms_vehicleModelStore.allocPtr; i++)
|
||||
ms_vehicleModelStore.store[i].Shutdown();
|
||||
}
|
||||
|
||||
CSimpleModelInfo*
|
||||
CModelInfo::AddSimpleModel(int id)
|
||||
{
|
||||
CSimpleModelInfo *modelinfo;
|
||||
modelinfo = CModelInfo::ms_simpleModelStore.alloc();
|
||||
CModelInfo::ms_modelInfoPtrs[id] = modelinfo;
|
||||
modelinfo->Init();
|
||||
return modelinfo;
|
||||
}
|
||||
|
||||
CTimeModelInfo*
|
||||
CModelInfo::AddTimeModel(int id)
|
||||
{
|
||||
CTimeModelInfo *modelinfo;
|
||||
modelinfo = CModelInfo::ms_timeModelStore.alloc();
|
||||
CModelInfo::ms_modelInfoPtrs[id] = modelinfo;
|
||||
modelinfo->Init();
|
||||
return modelinfo;
|
||||
}
|
||||
|
||||
CClumpModelInfo*
|
||||
CModelInfo::AddClumpModel(int id)
|
||||
{
|
||||
CClumpModelInfo *modelinfo;
|
||||
modelinfo = CModelInfo::ms_clumpModelStore.alloc();
|
||||
CModelInfo::ms_modelInfoPtrs[id] = modelinfo;
|
||||
modelinfo->m_clump = nil;
|
||||
return modelinfo;
|
||||
}
|
||||
|
||||
CPedModelInfo*
|
||||
CModelInfo::AddPedModel(int id)
|
||||
{
|
||||
CPedModelInfo *modelinfo;
|
||||
modelinfo = CModelInfo::ms_pedModelStore.alloc();
|
||||
CModelInfo::ms_modelInfoPtrs[id] = modelinfo;
|
||||
modelinfo->m_clump = nil;
|
||||
return modelinfo;
|
||||
}
|
||||
|
||||
CVehicleModelInfo*
|
||||
CModelInfo::AddVehicleModel(int id)
|
||||
{
|
||||
CVehicleModelInfo *modelinfo;
|
||||
modelinfo = CModelInfo::ms_vehicleModelStore.alloc();
|
||||
CModelInfo::ms_modelInfoPtrs[id] = modelinfo;
|
||||
modelinfo->m_clump = nil;
|
||||
modelinfo->m_vehicleType = -1;
|
||||
modelinfo->m_wheelId = -1;
|
||||
modelinfo->m_materials1[0] = nil;
|
||||
modelinfo->m_materials2[0] = nil;
|
||||
modelinfo->m_bikeSteerAngle = 999.99f;
|
||||
return modelinfo;
|
||||
}
|
||||
|
||||
CBaseModelInfo*
|
||||
CModelInfo::GetModelInfo(const char *name, int *id)
|
||||
{
|
||||
CBaseModelInfo *modelinfo;
|
||||
for(int i = 0; i < MODELINFOSIZE; i++){
|
||||
modelinfo = CModelInfo::ms_modelInfoPtrs[i];
|
||||
if(modelinfo && _strcmpi(modelinfo->GetName(), name) == 0){
|
||||
if(id)
|
||||
*id = i;
|
||||
return modelinfo;
|
||||
}
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
STARTPATCHES
|
||||
// InjectHook(0x50B920, CModelInfo::AddSimpleModel, PATCH_JUMP);
|
||||
// InjectHook(0x50B9C0, CModelInfo::AddTimeModel, PATCH_JUMP);
|
||||
// InjectHook(0x50BA10, CModelInfo::AddClumpModel, PATCH_JUMP);
|
||||
// InjectHook(0x50BAD0, CModelInfo::AddPedModel, PATCH_JUMP);
|
||||
// InjectHook(0x50BA60, CModelInfo::AddPedModel, PATCH_JUMP);
|
||||
InjectHook(0x50B860, (CBaseModelInfo *(*)(const char*, int*))CModelInfo::GetModelInfo, PATCH_JUMP);
|
||||
ENDPATCHES
|
35
src/modelinfo/ModelInfo.h
Normal file
35
src/modelinfo/ModelInfo.h
Normal file
@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
#include "2dEffect.h"
|
||||
#include "BaseModelInfo.h"
|
||||
#include "SimpleModelInfo.h"
|
||||
#include "TimeModelInfo.h"
|
||||
#include "ClumpModelInfo.h"
|
||||
#include "PedModelInfo.h"
|
||||
#include "VehicleModelInfo.h"
|
||||
|
||||
class CModelInfo
|
||||
{
|
||||
static CBaseModelInfo **ms_modelInfoPtrs; //[MODELINFOSIZE];
|
||||
static CStore<CSimpleModelInfo, SIMPLEMODELSIZE> ms_simpleModelStore;
|
||||
static CStore<CTimeModelInfo, TIMEMODELSIZE> ms_timeModelStore;
|
||||
static CStore<CClumpModelInfo, CLUMPMODELSIZE> ms_clumpModelStore;
|
||||
static CStore<CPedModelInfo, PEDMODELSIZE> ms_pedModelStore;
|
||||
static CStore<CVehicleModelInfo, VEHICLEMODELSIZE> ms_vehicleModelStore;
|
||||
static CStore<C2dEffect, TWODFXSIZE> ms_2dEffectStore;
|
||||
|
||||
public:
|
||||
static void Initialise(void);
|
||||
static void Shutdown(void);
|
||||
|
||||
static CSimpleModelInfo *AddSimpleModel(int id);
|
||||
static CTimeModelInfo *AddTimeModel(int id);
|
||||
static CClumpModelInfo *AddClumpModel(int id);
|
||||
static CPedModelInfo *AddPedModel(int id);
|
||||
static CVehicleModelInfo *AddVehicleModel(int id);
|
||||
|
||||
static CBaseModelInfo *GetModelInfo(const char *name, int *id);
|
||||
static CBaseModelInfo *GetModelInfo(int id){
|
||||
return ms_modelInfoPtrs[id];
|
||||
}
|
||||
};
|
197
src/modelinfo/PedModelInfo.cpp
Normal file
197
src/modelinfo/PedModelInfo.cpp
Normal file
@ -0,0 +1,197 @@
|
||||
#include "common.h"
|
||||
#include "patcher.h"
|
||||
#include "NodeName.h"
|
||||
#include "VisibilityPlugins.h"
|
||||
#include "ModelInfo.h"
|
||||
|
||||
void
|
||||
CPedModelInfo::DeleteRwObject(void)
|
||||
{
|
||||
CClumpModelInfo::DeleteRwObject();
|
||||
if(m_hitColModel)
|
||||
delete m_hitColModel;
|
||||
m_hitColModel = nil;
|
||||
}
|
||||
|
||||
RwObjectNameIdAssocation CPedModelInfo::m_pPedIds[12] = {
|
||||
{ "Smid", PED_TORSO, 0, }, // that is strange...
|
||||
{ "Shead", PED_HEAD, 0, },
|
||||
{ "Supperarml", PED_UPPERARML, 0, },
|
||||
{ "Supperarmr", PED_UPPERARMR, 0, },
|
||||
{ "SLhand", PED_HANDL, 0, },
|
||||
{ "SRhand", PED_HANDR, 0, },
|
||||
{ "Supperlegl", PED_UPPERLEGL, 0, },
|
||||
{ "Supperlegr", PED_UPPERLEGR, 0, },
|
||||
{ "Sfootl", PED_FOOTL, 0, },
|
||||
{ "Sfootr", PED_FOOTR, 0, },
|
||||
{ "Slowerlegr", PED_LOWERLEGR, 0, },
|
||||
{ NULL, 0, 0, },
|
||||
};
|
||||
|
||||
void
|
||||
CPedModelInfo::SetClump(RpClump *clump)
|
||||
{
|
||||
CClumpModelInfo::SetClump(clump);
|
||||
SetFrameIds(m_pPedIds);
|
||||
if(m_hitColModel == nil)
|
||||
CreateHitColModel();
|
||||
if(strncmp(GetName(), "player", 7) == 0)
|
||||
RpClumpForAllAtomics(m_clump, SetAtomicRendererCB, CVisibilityPlugins::RenderPlayerCB);
|
||||
}
|
||||
|
||||
RpAtomic*
|
||||
CountAtomicsCB(RpAtomic *atomic, void *data)
|
||||
{
|
||||
(*(int32*)data)++;
|
||||
return atomic;
|
||||
}
|
||||
|
||||
RpAtomic*
|
||||
GetAtomicListCB(RpAtomic *atomic, void *data)
|
||||
{
|
||||
**(RpAtomic***)data = atomic;
|
||||
(*(RpAtomic***)data)++;
|
||||
return atomic;
|
||||
}
|
||||
|
||||
RwFrame*
|
||||
FindPedFrameFromNameCB(RwFrame *frame, void *data)
|
||||
{
|
||||
RwObjectNameAssociation *assoc = (RwObjectNameAssociation*)data;
|
||||
|
||||
if(_strcmpi(GetFrameNodeName(frame)+1, assoc->name+1) != 0){
|
||||
RwFrameForAllChildren(frame, FindPedFrameFromNameCB, assoc);
|
||||
return assoc->frame ? nil : frame;
|
||||
}else{
|
||||
assoc->frame = frame;
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CPedModelInfo::SetLowDetailClump(RpClump *lodclump)
|
||||
{
|
||||
RpAtomic *atomics[16];
|
||||
RpAtomic **pAtm;
|
||||
int32 numAtm, numLodAtm;
|
||||
int i;
|
||||
RwObjectNameAssociation assoc;
|
||||
|
||||
numAtm = 0;
|
||||
numLodAtm = 0;
|
||||
RpClumpForAllAtomics(m_clump, CountAtomicsCB, &numAtm); // actually unused
|
||||
RpClumpForAllAtomics(lodclump, CountAtomicsCB, &numLodAtm);
|
||||
|
||||
RpClumpForAllAtomics(m_clump, SetAtomicRendererCB, CVisibilityPlugins::RenderPedHiDetailCB);
|
||||
RpClumpForAllAtomics(lodclump, SetAtomicRendererCB, CVisibilityPlugins::RenderPedLowDetailCB);
|
||||
|
||||
pAtm = atomics;
|
||||
RpClumpForAllAtomics(lodclump, GetAtomicListCB, &pAtm);
|
||||
|
||||
for(i = 0; i < numLodAtm; i++){
|
||||
assoc.name = GetFrameNodeName(RpAtomicGetFrame(atomics[i]));
|
||||
assoc.frame = nil;
|
||||
RwFrameForAllChildren(RpClumpGetFrame(m_clump), FindPedFrameFromNameCB, &assoc);
|
||||
if(assoc.frame){
|
||||
RpAtomicSetFrame(atomics[i], assoc.frame);
|
||||
RpClumpRemoveAtomic(lodclump, atomics[i]);
|
||||
RpClumpAddAtomic(m_clump, atomics[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct ColNodeInfo
|
||||
{
|
||||
char *name;
|
||||
int pedNode;
|
||||
int pieceType;
|
||||
float x, z;
|
||||
float radius;
|
||||
};
|
||||
|
||||
// TODO: find out piece types
|
||||
#define NUMPEDINFONODES 8
|
||||
ColNodeInfo m_pColNodeInfos[NUMPEDINFONODES] = {
|
||||
{ NULL, PED_HEAD, 6, 0.0f, 0.05f, 0.2f },
|
||||
{ "Storso", 0, 0, 0.0f, 0.15f, 0.2f },
|
||||
{ "Storso", 0, 0, 0.0f, -0.05f, 0.3f },
|
||||
{ NULL, PED_TORSO, 1, 0.0f, -0.07f, 0.3f },
|
||||
{ NULL, PED_UPPERARML, 2, 0.07f, -0.1f, 0.2f },
|
||||
{ NULL, PED_UPPERARMR, 3, -0.07f, -0.1f, 0.2f },
|
||||
{ "Slowerlegl", 0, 4, 0.0f, 0.07f, 0.25f },
|
||||
{ NULL, PED_LOWERLEGR, 5, 0.0f, 0.07f, 0.25f },
|
||||
};
|
||||
|
||||
RwObject*
|
||||
FindHeadRadiusCB(RwObject *object, void *data)
|
||||
{
|
||||
RpAtomic *atomic = (RpAtomic*)object;
|
||||
*(float*)data = RpAtomicGetBoundingSphere(atomic)->radius;
|
||||
return nil;
|
||||
}
|
||||
|
||||
void
|
||||
CPedModelInfo::CreateHitColModel(void)
|
||||
{
|
||||
RwObjectNameAssociation nameAssoc;
|
||||
RwObjectIdAssociation idAssoc;
|
||||
CVector center;
|
||||
RwFrame *nodeFrame;
|
||||
CColModel *colmodel = new CColModel;
|
||||
CColSphere *spheres = (CColSphere*)RwMalloc(NUMPEDINFONODES*sizeof(CColSphere));
|
||||
RwFrame *root = RpClumpGetFrame(m_clump);
|
||||
RwMatrix *mat = RwMatrixCreate();
|
||||
for(int i = 0; i < NUMPEDINFONODES; i++){
|
||||
nodeFrame = nil;
|
||||
if(m_pColNodeInfos[i].name){
|
||||
nameAssoc.name = m_pColNodeInfos[i].name;
|
||||
nameAssoc.frame = nil;
|
||||
RwFrameForAllChildren(root, FindFrameFromNameCB, &nameAssoc);
|
||||
nodeFrame = nameAssoc.frame;
|
||||
}else{
|
||||
idAssoc.id = m_pColNodeInfos[i].pedNode;
|
||||
idAssoc.frame = nil;
|
||||
RwFrameForAllChildren(root, FindFrameFromIdCB, &idAssoc);
|
||||
nodeFrame = idAssoc.frame;
|
||||
}
|
||||
if(nodeFrame){
|
||||
float radius = m_pColNodeInfos[i].radius;
|
||||
if(m_pColNodeInfos[i].pieceType == 6)
|
||||
RwFrameForAllObjects(nodeFrame, FindHeadRadiusCB, &radius);
|
||||
RwMatrixTransform(mat, RwFrameGetMatrix(nodeFrame), rwCOMBINEREPLACE);
|
||||
const char *name = GetFrameNodeName(nodeFrame);
|
||||
for(nodeFrame = RwFrameGetParent(nodeFrame);
|
||||
nodeFrame;
|
||||
nodeFrame = RwFrameGetParent(nodeFrame)){
|
||||
name = GetFrameNodeName(nodeFrame);
|
||||
RwMatrixTransform(mat, RwFrameGetMatrix(nodeFrame), rwCOMBINEPOSTCONCAT);
|
||||
if(RwFrameGetParent(nodeFrame) == root)
|
||||
break;
|
||||
}
|
||||
center.x = mat->pos.x + m_pColNodeInfos[i].x;
|
||||
center.y = mat->pos.y + 0.0f;
|
||||
center.z = mat->pos.z + m_pColNodeInfos[i].z;
|
||||
spheres[i].Set(radius, center, 17, m_pColNodeInfos[i].pieceType);
|
||||
}
|
||||
}
|
||||
RwMatrixDestroy(mat);
|
||||
colmodel->spheres = spheres;
|
||||
colmodel->numSpheres = NUMPEDINFONODES;
|
||||
center.x = center.y = center.z = 0.0f;
|
||||
colmodel->boundingSphere.Set(2.0f, center, 0, 0);
|
||||
CVector min, max;
|
||||
min.x = min.y = -0.5f;
|
||||
min.z = -1.2f;
|
||||
max.x = max.y = 0.5f;
|
||||
max.z = 1.2f;
|
||||
colmodel->boundingBox.Set(min, max, 0, 0);
|
||||
colmodel->level = 0;
|
||||
m_hitColModel = colmodel;
|
||||
}
|
||||
|
||||
STARTPATCHES
|
||||
InjectHook(0x510210, &CPedModelInfo::SetClump_, PATCH_JUMP);
|
||||
InjectHook(0x510280, &CPedModelInfo::DeleteRwObject_, PATCH_JUMP);
|
||||
InjectHook(0x510390, &CPedModelInfo::SetLowDetailClump, PATCH_JUMP);
|
||||
InjectHook(0x5104D0, &CPedModelInfo::CreateHitColModel, PATCH_JUMP);
|
||||
ENDPATCHES
|
47
src/modelinfo/PedModelInfo.h
Normal file
47
src/modelinfo/PedModelInfo.h
Normal file
@ -0,0 +1,47 @@
|
||||
#pragma once
|
||||
|
||||
#include "ClumpModelInfo.h"
|
||||
|
||||
enum PedNode {
|
||||
PED_WAIST,
|
||||
PED_TORSO, // Smid on PS2/PC, Storso on mobile/xbox
|
||||
PED_HEAD,
|
||||
PED_UPPERARML,
|
||||
PED_UPPERARMR,
|
||||
PED_HANDL,
|
||||
PED_HANDR,
|
||||
PED_UPPERLEGL,
|
||||
PED_UPPERLEGR,
|
||||
PED_FOOTL,
|
||||
PED_FOOTR,
|
||||
PED_LOWERLEGR,
|
||||
// This is not valid apparently
|
||||
PED_LOWERLEGL,
|
||||
};
|
||||
|
||||
class CPedModelInfo : public CClumpModelInfo
|
||||
{
|
||||
public:
|
||||
void *m_animGroup; // TODO
|
||||
int32 m_pedType;
|
||||
int32 m_pedStatType;
|
||||
uint32 m_carsCanDrive;
|
||||
CColModel *m_hitColModel;
|
||||
RpAtomic *m_head;
|
||||
RpAtomic *m_lhand;
|
||||
RpAtomic *m_rhand;
|
||||
|
||||
static RwObjectNameIdAssocation m_pPedIds[12];
|
||||
|
||||
CPedModelInfo(void) : CClumpModelInfo(MITYPE_PED) { }
|
||||
void DeleteRwObject(void);
|
||||
void SetClump(RpClump *);
|
||||
|
||||
void SetLowDetailClump(RpClump*);
|
||||
void CreateHitColModel(void);
|
||||
|
||||
|
||||
void DeleteRwObject_(void) { this->CPedModelInfo::DeleteRwObject(); }
|
||||
void SetClump_(RpClump *clump) { this->CPedModelInfo::SetClump(clump); }
|
||||
};
|
||||
static_assert(sizeof(CPedModelInfo) == 0x54, "CPedModelInfo: error");
|
174
src/modelinfo/SimpleModelInfo.cpp
Normal file
174
src/modelinfo/SimpleModelInfo.cpp
Normal file
@ -0,0 +1,174 @@
|
||||
#include "common.h"
|
||||
#include "patcher.h"
|
||||
#include "Camera.h"
|
||||
#include "ModelInfo.h"
|
||||
|
||||
#define LOD_DISTANCE (300.0f)
|
||||
|
||||
void
|
||||
CSimpleModelInfo::DeleteRwObject(void)
|
||||
{
|
||||
int i;
|
||||
RwFrame *f;
|
||||
for(i = 0; i < m_numAtomics; i++)
|
||||
if(m_atomics[i]){
|
||||
f = RpAtomicGetFrame(m_atomics[i]);
|
||||
RpAtomicDestroy(m_atomics[i]);
|
||||
RwFrameDestroy(f);
|
||||
m_atomics[i] = nil;
|
||||
RemoveTexDictionaryRef();
|
||||
}
|
||||
}
|
||||
|
||||
RwObject*
|
||||
CSimpleModelInfo::CreateInstance(void)
|
||||
{
|
||||
RpAtomic *atomic;
|
||||
if(m_atomics[0] == nil)
|
||||
return nil;
|
||||
atomic = RpAtomicClone(m_atomics[0]);
|
||||
RpAtomicSetFrame(atomic, RwFrameCreate());
|
||||
return (RwObject*)atomic;
|
||||
}
|
||||
|
||||
RwObject*
|
||||
CSimpleModelInfo::CreateInstance(RwMatrix *matrix)
|
||||
{
|
||||
RpAtomic *atomic;
|
||||
RwFrame *frame;
|
||||
|
||||
if(m_atomics[0] == nil)
|
||||
return nil;
|
||||
atomic = RpAtomicClone(m_atomics[0]);
|
||||
frame = RwFrameCreate();
|
||||
*RwFrameGetMatrix(frame) = *matrix;
|
||||
RpAtomicSetFrame(atomic, frame);
|
||||
return (RwObject*)atomic;
|
||||
}
|
||||
|
||||
void
|
||||
CSimpleModelInfo::Init(void)
|
||||
{
|
||||
m_atomics[0] = nil;
|
||||
m_atomics[1] = nil;
|
||||
m_atomics[2] = nil;
|
||||
m_numAtomics = 0;
|
||||
m_furthest = 0;
|
||||
m_normalCull = 0;
|
||||
m_isDamaged = 0;
|
||||
m_isBigBuilding = 0;
|
||||
m_noFade = 0;
|
||||
m_drawLast = 0;
|
||||
m_additive = 0;
|
||||
m_isSubway = 0;
|
||||
m_ignoreLight = 0;
|
||||
m_noZwrite = 0;
|
||||
}
|
||||
|
||||
void
|
||||
CSimpleModelInfo::SetAtomic(int n, RpAtomic *atomic)
|
||||
{
|
||||
AddTexDictionaryRef();
|
||||
m_atomics[n] = atomic;
|
||||
if(m_ignoreLight){
|
||||
RpGeometry *geo = RpAtomicGetGeometry(atomic);
|
||||
RpGeometrySetFlags(geo, RpGeometryGetFlags(geo) & ~rpGEOMETRYLIGHT);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CSimpleModelInfo::SetLodDistances(float *dist)
|
||||
{
|
||||
m_lodDistances[0] = dist[0];
|
||||
m_lodDistances[1] = dist[1];
|
||||
m_lodDistances[2] = dist[2];
|
||||
}
|
||||
|
||||
void
|
||||
CSimpleModelInfo::IncreaseAlpha(void)
|
||||
{
|
||||
if(m_alpha >= 0xEF)
|
||||
m_alpha = 0xFF;
|
||||
else
|
||||
m_alpha += 0x10;
|
||||
}
|
||||
|
||||
float
|
||||
CSimpleModelInfo::GetNearDistance(void)
|
||||
{
|
||||
return m_lodDistances[2] * TheCamera.LODDistMultiplier;
|
||||
}
|
||||
|
||||
float
|
||||
CSimpleModelInfo::GetLargestLodDistance(void)
|
||||
{
|
||||
float d;
|
||||
// TODO: what exactly is going on here?
|
||||
if(m_furthest != 0 && !m_isDamaged)
|
||||
d = m_lodDistances[m_furthest-1];
|
||||
else
|
||||
d = m_lodDistances[m_numAtomics-1];
|
||||
return d * TheCamera.LODDistMultiplier;
|
||||
}
|
||||
|
||||
RpAtomic*
|
||||
CSimpleModelInfo::GetAtomicFromDistance(float dist)
|
||||
{
|
||||
int i;
|
||||
i = 0;
|
||||
// TODO: what exactly is going on here?
|
||||
if(m_isDamaged)
|
||||
i = m_furthest;
|
||||
for(; i < m_numAtomics; i++)
|
||||
if(dist < m_lodDistances[i] *TheCamera.LODDistMultiplier)
|
||||
return m_atomics[i];
|
||||
return nil;
|
||||
}
|
||||
|
||||
void
|
||||
CSimpleModelInfo::FindRelatedModel(void)
|
||||
{
|
||||
int i;
|
||||
CBaseModelInfo *mi;
|
||||
for(i = 0; i < MODELINFOSIZE; i++){
|
||||
mi = CModelInfo::GetModelInfo(i);
|
||||
if(mi && mi != this &&
|
||||
strcmp(GetName()+3, mi->GetName()+3) == 0){
|
||||
assert(mi->IsSimple());
|
||||
this->SetRelatedModel((CSimpleModelInfo*)mi);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CSimpleModelInfo::SetupBigBuilding(void)
|
||||
{
|
||||
CSimpleModelInfo *related;
|
||||
if(m_lodDistances[0] > LOD_DISTANCE && m_atomics[2] == nil){
|
||||
m_isBigBuilding = 1;
|
||||
FindRelatedModel();
|
||||
related = GetRelatedModel();
|
||||
if(related)
|
||||
m_lodDistances[2] = related->GetLargestLodDistance()/TheCamera.LODDistMultiplier;
|
||||
else
|
||||
m_lodDistances[2] = 100.0f;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
STARTPATCHES
|
||||
InjectHook(0x5179B0, &CSimpleModelInfo::DeleteRwObject_, PATCH_JUMP);
|
||||
InjectHook(0x517B60, &CSimpleModelInfo::CreateInstance_1, PATCH_JUMP);
|
||||
InjectHook(0x517AC0, &CSimpleModelInfo::CreateInstance_2, PATCH_JUMP);
|
||||
InjectHook(0x4A9BA0, &CSimpleModelInfo::GetRwObject_, PATCH_JUMP);
|
||||
InjectHook(0x517990, &CSimpleModelInfo::Init, PATCH_JUMP);
|
||||
InjectHook(0x517C60, &CSimpleModelInfo::IncreaseAlpha, PATCH_JUMP);
|
||||
InjectHook(0x517950, &CSimpleModelInfo::SetAtomic, PATCH_JUMP);
|
||||
InjectHook(0x517AA0, &CSimpleModelInfo::SetLodDistances, PATCH_JUMP);
|
||||
InjectHook(0x517A90, &CSimpleModelInfo::GetNearDistance, PATCH_JUMP);
|
||||
InjectHook(0x517A60, &CSimpleModelInfo::GetLargestLodDistance, PATCH_JUMP);
|
||||
InjectHook(0x517A00, &CSimpleModelInfo::GetAtomicFromDistance, PATCH_JUMP);
|
||||
InjectHook(0x517C00, &CSimpleModelInfo::FindRelatedModel, PATCH_JUMP);
|
||||
InjectHook(0x517B90, &CSimpleModelInfo::SetupBigBuilding, PATCH_JUMP);
|
||||
ENDPATCHES
|
57
src/modelinfo/SimpleModelInfo.h
Normal file
57
src/modelinfo/SimpleModelInfo.h
Normal file
@ -0,0 +1,57 @@
|
||||
#pragma once
|
||||
|
||||
#include "BaseModelInfo.h"
|
||||
|
||||
class CSimpleModelInfo : public CBaseModelInfo
|
||||
{
|
||||
public:
|
||||
// atomics[2] is often a pointer to the non-LOD modelinfo
|
||||
RpAtomic *m_atomics[3];
|
||||
// m_lodDistances[2] holds the near distance for LODs
|
||||
float m_lodDistances[3];
|
||||
uint8 m_numAtomics;
|
||||
uint8 m_alpha;
|
||||
uint16 m_furthest : 2; // 0: numAtomics-1 is furthest visible
|
||||
// 1: atomic 0 is furthest
|
||||
// 2: atomic 1 is furthest
|
||||
uint16 m_normalCull : 1;
|
||||
uint16 m_isDamaged : 1;
|
||||
uint16 m_isBigBuilding : 1;
|
||||
uint16 m_noFade : 1;
|
||||
uint16 m_drawLast : 1;
|
||||
uint16 m_additive : 1;
|
||||
uint16 m_isSubway : 1;
|
||||
uint16 m_ignoreLight : 1;
|
||||
uint16 m_noZwrite : 1;
|
||||
|
||||
CSimpleModelInfo(void) : CBaseModelInfo(MITYPE_SIMPLE) {}
|
||||
CSimpleModelInfo(ModeInfoType id) : CBaseModelInfo(id) {}
|
||||
~CSimpleModelInfo() {}
|
||||
void DeleteRwObject(void);
|
||||
RwObject *CreateInstance(void);
|
||||
RwObject *CreateInstance(RwMatrix *);
|
||||
RwObject *GetRwObject(void) { return (RwObject*)m_atomics[0]; }
|
||||
|
||||
void Init(void);
|
||||
void IncreaseAlpha(void);
|
||||
void SetAtomic(int n, RpAtomic *atomic);
|
||||
void SetLodDistances(float *dist);
|
||||
float GetLodDistance(int i) { return m_lodDistances[i]; }
|
||||
float GetNearDistance(void);
|
||||
float GetLargestLodDistance(void);
|
||||
RpAtomic *GetAtomicFromDistance(float dist);
|
||||
void FindRelatedModel(void);
|
||||
void SetupBigBuilding(void);
|
||||
|
||||
void SetNumAtomics(int n) { m_numAtomics = n; }
|
||||
CSimpleModelInfo *GetRelatedModel(void){
|
||||
return (CSimpleModelInfo*)m_atomics[2]; }
|
||||
void SetRelatedModel(CSimpleModelInfo *m){
|
||||
m_atomics[2] = (RpAtomic*)m; }
|
||||
|
||||
void DeleteRwObject_(void) { this->CSimpleModelInfo::DeleteRwObject(); }
|
||||
RwObject *CreateInstance_1(void) { return this->CSimpleModelInfo::CreateInstance(); }
|
||||
RwObject *CreateInstance_2(RwMatrix *m) { return this->CSimpleModelInfo::CreateInstance(m); }
|
||||
RwObject *GetRwObject_(void) { return this->CSimpleModelInfo::GetRwObject(); }
|
||||
};
|
||||
static_assert(sizeof(CSimpleModelInfo) == 0x4C, "CSimpleModelInfo: error");
|
36
src/modelinfo/TimeModelInfo.cpp
Normal file
36
src/modelinfo/TimeModelInfo.cpp
Normal file
@ -0,0 +1,36 @@
|
||||
#include "common.h"
|
||||
#include "patcher.h"
|
||||
#include "Camera.h"
|
||||
#include "ModelInfo.h"
|
||||
|
||||
CTimeModelInfo*
|
||||
CTimeModelInfo::FindOtherTimeModel(void)
|
||||
{
|
||||
char name[40];
|
||||
char *p;
|
||||
int i;
|
||||
|
||||
strcpy(name, GetName());
|
||||
// change _nt to _dy
|
||||
if(p = strstr(name, "_nt"))
|
||||
strncpy(p, "_dy", 4);
|
||||
// change _dy to _nt
|
||||
else if(p = strstr(name, "_dy"))
|
||||
strncpy(p, "_nt", 4);
|
||||
else
|
||||
return nil;
|
||||
|
||||
for(i = 0; i < MODELINFOSIZE; i++){
|
||||
CBaseModelInfo *mi = CModelInfo::GetModelInfo(i);
|
||||
if(mi && mi->m_type == MITYPE_TIME &&
|
||||
strncmp(name, mi->GetName(), 24) == 0){
|
||||
m_otherTimeModelID = i;
|
||||
return (CTimeModelInfo*)mi;
|
||||
}
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
STARTPATCHES
|
||||
InjectHook(0x517C80, &CTimeModelInfo::FindOtherTimeModel, PATCH_JUMP);
|
||||
ENDPATCHES
|
18
src/modelinfo/TimeModelInfo.h
Normal file
18
src/modelinfo/TimeModelInfo.h
Normal file
@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include "SimpleModelInfo.h"
|
||||
|
||||
class CTimeModelInfo : public CSimpleModelInfo
|
||||
{
|
||||
int32 m_timeOn;
|
||||
int32 m_timeOff;
|
||||
int32 m_otherTimeModelID;
|
||||
public:
|
||||
CTimeModelInfo(void) : CSimpleModelInfo(MITYPE_TIME) { m_otherTimeModelID = -1; }
|
||||
|
||||
int32 GetTimeOn(void) { return m_timeOn; }
|
||||
int32 GetTimeOff(void) { return m_timeOff; }
|
||||
int32 GetOtherTimeModel(void) { return m_otherTimeModelID; }
|
||||
CTimeModelInfo *FindOtherTimeModel(void);
|
||||
};
|
||||
static_assert(sizeof(CTimeModelInfo) == 0x58, "CTimeModelInfo: error");
|
917
src/modelinfo/VehicleModelInfo.cpp
Normal file
917
src/modelinfo/VehicleModelInfo.cpp
Normal file
@ -0,0 +1,917 @@
|
||||
#include "common.h"
|
||||
#include <rpmatfx.h>
|
||||
#include "patcher.h"
|
||||
#include "RwHelper.h"
|
||||
#include "General.h"
|
||||
#include "NodeName.h"
|
||||
#include "TxdStore.h"
|
||||
#include "Weather.h"
|
||||
#include "VisibilityPlugins.h"
|
||||
#include "ModelInfo.h"
|
||||
|
||||
int8 *CVehicleModelInfo::ms_compsToUse = (int8*)0x5FF2EC; // -2, -2
|
||||
int8 *CVehicleModelInfo::ms_compsUsed = (int8*)0x95CCB2;
|
||||
RwTexture **CVehicleModelInfo::ms_pEnvironmentMaps = (RwTexture **)0x8F1A30;
|
||||
RwRGBA *CVehicleModelInfo::ms_vehicleColourTable = (RwRGBA*)0x86BA88;
|
||||
RwTexture **CVehicleModelInfo::ms_colourTextureTable = (RwTexture**)0x711C40;
|
||||
|
||||
RwTexture *&gpWhiteTexture = *(RwTexture**)0x64C4F8;
|
||||
RwFrame *&pMatFxIdentityFrame = *(RwFrame**)0x64C510;
|
||||
|
||||
// TODO This depends on handling
|
||||
WRAPPER void CVehicleModelInfo::SetVehicleComponentFlags(RwFrame *frame, uint32 flags) { EAXJMP(0x5203C0); }
|
||||
|
||||
enum {
|
||||
CAR_WHEEL_RF = 1,
|
||||
CAR_WHEEL_RM = 2,
|
||||
CAR_WHEEL_RB = 3,
|
||||
CAR_WHEEL_LF = 4,
|
||||
CAR_WHEEL_LM = 5,
|
||||
CAR_WHEEL_LB = 6,
|
||||
CAR_BUMP_FRONT = 7,
|
||||
CAR_BUMP_REAR = 8,
|
||||
CAR_WING_RF = 9,
|
||||
CAR_WING_RR = 10,
|
||||
CAR_DOOR_RF = 11,
|
||||
CAR_DOOR_RR = 12,
|
||||
CAR_WING_LF = 13,
|
||||
CAR_WING_LR = 14,
|
||||
CAR_DOOR_LF = 15,
|
||||
CAR_DOOR_LR = 16,
|
||||
CAR_BONNET = 17,
|
||||
CAR_BOOT = 18,
|
||||
CAR_WINDSCREEN = 19,
|
||||
|
||||
CAR_POS_HEADLIGHTS = 0,
|
||||
CAR_POS_TAILLIGHTS = 1,
|
||||
CAR_POS_FRONTSEAT = 2,
|
||||
CAR_POS_BACKSEAT = 3,
|
||||
CAR_POS_EXHAUST = 9,
|
||||
};
|
||||
|
||||
enum {
|
||||
VEHICLE_FLAG_COLLAPSE = 0x2,
|
||||
VEHICLE_FLAG_ADD_WHEEL = 0x4,
|
||||
VEHICLE_FLAG_POS = 0x8,
|
||||
VEHICLE_FLAG_DOOR = 0x10,
|
||||
VEHICLE_FLAG_LEFT = 0x20,
|
||||
VEHICLE_FLAG_RIGHT = 0x40,
|
||||
VEHICLE_FLAG_FRONT = 0x80,
|
||||
VEHICLE_FLAG_REAR = 0x100,
|
||||
VEHICLE_FLAG_COMP = 0x200,
|
||||
VEHICLE_FLAG_DRAWLAST = 0x400,
|
||||
VEHICLE_FLAG_WINDSCREEN = 0x800,
|
||||
VEHICLE_FLAG_ANGLECULL = 0x1000,
|
||||
VEHICLE_FLAG_REARDOOR = 0x2000,
|
||||
VEHICLE_FLAG_FRONTDOOR = 0x4000,
|
||||
};
|
||||
|
||||
RwObjectNameIdAssocation carIds[] = {
|
||||
{ "wheel_rf_dummy", CAR_WHEEL_RF, VEHICLE_FLAG_RIGHT | VEHICLE_FLAG_ADD_WHEEL },
|
||||
{ "wheel_rm_dummy", CAR_WHEEL_RM, VEHICLE_FLAG_RIGHT | VEHICLE_FLAG_ADD_WHEEL },
|
||||
{ "wheel_rb_dummy", CAR_WHEEL_RB, VEHICLE_FLAG_RIGHT | VEHICLE_FLAG_ADD_WHEEL },
|
||||
{ "wheel_lf_dummy", CAR_WHEEL_LF, VEHICLE_FLAG_LEFT | VEHICLE_FLAG_ADD_WHEEL },
|
||||
{ "wheel_lm_dummy", CAR_WHEEL_LM, VEHICLE_FLAG_LEFT | VEHICLE_FLAG_ADD_WHEEL },
|
||||
{ "wheel_lb_dummy", CAR_WHEEL_LB, VEHICLE_FLAG_LEFT | VEHICLE_FLAG_ADD_WHEEL },
|
||||
{ "bump_front_dummy", CAR_BUMP_FRONT, VEHICLE_FLAG_FRONT | VEHICLE_FLAG_COLLAPSE },
|
||||
{ "bonnet_dummy", CAR_BONNET, VEHICLE_FLAG_COLLAPSE },
|
||||
{ "wing_rf_dummy", CAR_WING_RF, VEHICLE_FLAG_COLLAPSE },
|
||||
{ "wing_rr_dummy", CAR_WING_RR, VEHICLE_FLAG_RIGHT | VEHICLE_FLAG_COLLAPSE },
|
||||
{ "door_rf_dummy", CAR_DOOR_RF, VEHICLE_FLAG_FRONTDOOR | VEHICLE_FLAG_ANGLECULL | VEHICLE_FLAG_RIGHT | VEHICLE_FLAG_DOOR | VEHICLE_FLAG_COLLAPSE },
|
||||
{ "door_rr_dummy", CAR_DOOR_RR, VEHICLE_FLAG_REARDOOR | VEHICLE_FLAG_ANGLECULL | VEHICLE_FLAG_REAR | VEHICLE_FLAG_RIGHT | VEHICLE_FLAG_DOOR | VEHICLE_FLAG_COLLAPSE },
|
||||
{ "wing_lf_dummy", CAR_WING_LF, VEHICLE_FLAG_COLLAPSE },
|
||||
{ "wing_lr_dummy", CAR_WING_LR, VEHICLE_FLAG_LEFT | VEHICLE_FLAG_COLLAPSE },
|
||||
{ "door_lf_dummy", CAR_DOOR_LF, VEHICLE_FLAG_FRONTDOOR | VEHICLE_FLAG_ANGLECULL | VEHICLE_FLAG_LEFT | VEHICLE_FLAG_DOOR | VEHICLE_FLAG_COLLAPSE },
|
||||
{ "door_lr_dummy", CAR_DOOR_LR, VEHICLE_FLAG_REARDOOR | VEHICLE_FLAG_ANGLECULL | VEHICLE_FLAG_REAR | VEHICLE_FLAG_LEFT | VEHICLE_FLAG_DOOR | VEHICLE_FLAG_COLLAPSE },
|
||||
{ "boot_dummy", CAR_BOOT, VEHICLE_FLAG_REAR | VEHICLE_FLAG_COLLAPSE },
|
||||
{ "bump_rear_dummy", CAR_BUMP_REAR, VEHICLE_FLAG_REAR | VEHICLE_FLAG_COLLAPSE },
|
||||
{ "windscreen_dummy", CAR_WINDSCREEN, VEHICLE_FLAG_WINDSCREEN | VEHICLE_FLAG_DRAWLAST | VEHICLE_FLAG_FRONT | VEHICLE_FLAG_COLLAPSE },
|
||||
|
||||
{ "ped_frontseat", CAR_POS_FRONTSEAT, VEHICLE_FLAG_POS | CLUMP_FLAG_NO_HIERID },
|
||||
{ "ped_backseat", CAR_POS_BACKSEAT, VEHICLE_FLAG_POS | CLUMP_FLAG_NO_HIERID },
|
||||
{ "headlights", CAR_POS_HEADLIGHTS, VEHICLE_FLAG_POS | CLUMP_FLAG_NO_HIERID },
|
||||
{ "taillights", CAR_POS_TAILLIGHTS, VEHICLE_FLAG_POS | CLUMP_FLAG_NO_HIERID },
|
||||
{ "exhaust", CAR_POS_EXHAUST, VEHICLE_FLAG_POS | CLUMP_FLAG_NO_HIERID },
|
||||
{ "extra1", 0, VEHICLE_FLAG_DRAWLAST | VEHICLE_FLAG_COMP | CLUMP_FLAG_NO_HIERID },
|
||||
{ "extra2", 0, VEHICLE_FLAG_DRAWLAST | VEHICLE_FLAG_COMP | CLUMP_FLAG_NO_HIERID },
|
||||
{ "extra3", 0, VEHICLE_FLAG_DRAWLAST | VEHICLE_FLAG_COMP | CLUMP_FLAG_NO_HIERID },
|
||||
{ "extra4", 0, VEHICLE_FLAG_DRAWLAST | VEHICLE_FLAG_COMP | CLUMP_FLAG_NO_HIERID },
|
||||
{ "extra5", 0, VEHICLE_FLAG_DRAWLAST | VEHICLE_FLAG_COMP | CLUMP_FLAG_NO_HIERID },
|
||||
{ "extra6", 0, VEHICLE_FLAG_DRAWLAST | VEHICLE_FLAG_COMP | CLUMP_FLAG_NO_HIERID },
|
||||
{ nil, 0, 0 }
|
||||
};
|
||||
|
||||
RwObjectNameIdAssocation boatIds[] = {
|
||||
{ "boat_moving_hi", 1, VEHICLE_FLAG_COLLAPSE },
|
||||
{ "boat_rudder_hi", 3, VEHICLE_FLAG_COLLAPSE },
|
||||
{ "windscreen", 2, VEHICLE_FLAG_WINDSCREEN | VEHICLE_FLAG_COLLAPSE },
|
||||
{ "ped_frontseat", 0, VEHICLE_FLAG_POS | CLUMP_FLAG_NO_HIERID },
|
||||
{ nil, 0, 0 }
|
||||
};
|
||||
|
||||
RwObjectNameIdAssocation trainIds[] = {
|
||||
{ "door_lhs_dummy", 1, VEHICLE_FLAG_LEFT | VEHICLE_FLAG_COLLAPSE },
|
||||
{ "door_rhs_dummy", 2, VEHICLE_FLAG_LEFT | VEHICLE_FLAG_COLLAPSE },
|
||||
{ "light_front", 0, VEHICLE_FLAG_POS | CLUMP_FLAG_NO_HIERID },
|
||||
{ "light_rear", 1, VEHICLE_FLAG_POS | CLUMP_FLAG_NO_HIERID },
|
||||
{ "ped_left_entry", 2, VEHICLE_FLAG_DOOR | VEHICLE_FLAG_POS | CLUMP_FLAG_NO_HIERID },
|
||||
{ "ped_mid_entry", 3, VEHICLE_FLAG_DOOR | VEHICLE_FLAG_POS | CLUMP_FLAG_NO_HIERID },
|
||||
{ "ped_right_entry", 4, VEHICLE_FLAG_DOOR | VEHICLE_FLAG_POS | CLUMP_FLAG_NO_HIERID },
|
||||
{ nil, 0, 0 }
|
||||
};
|
||||
|
||||
RwObjectNameIdAssocation heliIds[] = {
|
||||
{ "chassis_dummy", 1, VEHICLE_FLAG_COLLAPSE },
|
||||
{ "toprotor", 2, 0 },
|
||||
{ "backrotor", 3, 0 },
|
||||
{ "tail", 4, 0 },
|
||||
{ "topknot", 5, 0 },
|
||||
{ "skid_left", 6, 0 },
|
||||
{ "skid_right", 7, 0 },
|
||||
{ nil, 0, 0 }
|
||||
};
|
||||
|
||||
RwObjectNameIdAssocation planeIds[] = {
|
||||
{ "wheel_front_dummy", 2, 0 },
|
||||
{ "wheel_rear_dummy", 3, 0 },
|
||||
{ "light_tailplane", 2, VEHICLE_FLAG_POS | CLUMP_FLAG_NO_HIERID },
|
||||
{ "light_left", 0, VEHICLE_FLAG_POS | CLUMP_FLAG_NO_HIERID },
|
||||
{ "light_right", 1, VEHICLE_FLAG_POS | CLUMP_FLAG_NO_HIERID },
|
||||
{ nil, 0, 0 }
|
||||
};
|
||||
|
||||
RwObjectNameIdAssocation bikeIds[] = {
|
||||
{ "chassis_dummy", 1, 0 },
|
||||
{ "forks_front", 2, 0 },
|
||||
{ "forks_rear", 3, 0 },
|
||||
{ "wheel_front", 4, 0 },
|
||||
{ "wheel_rear", 5, 0 },
|
||||
{ "mudguard", 6, 0 },
|
||||
{ "ped_frontseat", 2, VEHICLE_FLAG_POS | CLUMP_FLAG_NO_HIERID },
|
||||
{ "headlights", 0, VEHICLE_FLAG_POS | CLUMP_FLAG_NO_HIERID },
|
||||
{ "taillights", 1, VEHICLE_FLAG_POS | CLUMP_FLAG_NO_HIERID },
|
||||
{ "exhaust", 9, VEHICLE_FLAG_POS | CLUMP_FLAG_NO_HIERID },
|
||||
{ "extra1", 0, VEHICLE_FLAG_DRAWLAST | VEHICLE_FLAG_COMP | CLUMP_FLAG_NO_HIERID },
|
||||
{ "extra2", 0, VEHICLE_FLAG_DRAWLAST | VEHICLE_FLAG_COMP | CLUMP_FLAG_NO_HIERID },
|
||||
{ "extra3", 0, VEHICLE_FLAG_DRAWLAST | VEHICLE_FLAG_COMP | CLUMP_FLAG_NO_HIERID },
|
||||
{ "extra4", 0, VEHICLE_FLAG_DRAWLAST | VEHICLE_FLAG_COMP | CLUMP_FLAG_NO_HIERID },
|
||||
{ "extra5", 0, VEHICLE_FLAG_DRAWLAST | VEHICLE_FLAG_COMP | CLUMP_FLAG_NO_HIERID },
|
||||
{ "extra6", 0, VEHICLE_FLAG_DRAWLAST | VEHICLE_FLAG_COMP | CLUMP_FLAG_NO_HIERID },
|
||||
{ nil, 0, 0 }
|
||||
};
|
||||
|
||||
RwObjectNameIdAssocation *CVehicleModelInfo::ms_vehicleDescs[] = {
|
||||
carIds,
|
||||
boatIds,
|
||||
trainIds,
|
||||
heliIds,
|
||||
planeIds,
|
||||
bikeIds
|
||||
};
|
||||
|
||||
|
||||
CVehicleModelInfo::CVehicleModelInfo(void)
|
||||
: CClumpModelInfo(MITYPE_VEHICLE)
|
||||
{
|
||||
int32 i;
|
||||
for(i = 0; i < NUM_VEHICLE_POSITIONS; i++){
|
||||
m_positions[i].x = 0.0f;
|
||||
m_positions[i].y = 0.0f;
|
||||
m_positions[i].z = 0.0f;
|
||||
}
|
||||
m_numColours = 0;
|
||||
}
|
||||
|
||||
void
|
||||
CVehicleModelInfo::DeleteRwObject(void)
|
||||
{
|
||||
int32 i;
|
||||
RwFrame *f;
|
||||
|
||||
for(i = 0; i < m_numComps; i++){
|
||||
f = RpAtomicGetFrame(m_comps[i]);
|
||||
RpAtomicDestroy(m_comps[i]);
|
||||
RwFrameDestroy(f);
|
||||
}
|
||||
m_numComps = 0;
|
||||
CClumpModelInfo::DeleteRwObject();
|
||||
}
|
||||
|
||||
RwObject*
|
||||
CVehicleModelInfo::CreateInstance(void)
|
||||
{
|
||||
RpClump *clump;
|
||||
RpAtomic *atomic;
|
||||
RwFrame *clumpframe, *f;
|
||||
int32 comp1, comp2;
|
||||
|
||||
clump = (RpClump*)CClumpModelInfo::CreateInstance();
|
||||
if(m_numComps != 0){
|
||||
clumpframe = RpClumpGetFrame(clump);
|
||||
|
||||
comp1 = ChooseComponent();
|
||||
if(comp1 != -1){
|
||||
atomic = RpAtomicClone(m_comps[comp1]);
|
||||
f = RwFrameCreate();
|
||||
RwFrameTransform(f,
|
||||
RwFrameGetMatrix(RpAtomicGetFrame(m_comps[comp1])),
|
||||
rwCOMBINEREPLACE);
|
||||
RpAtomicSetFrame(atomic, f);
|
||||
RpClumpAddAtomic(clump, atomic);
|
||||
RwFrameAddChild(clumpframe, f);
|
||||
}
|
||||
ms_compsUsed[0] = comp1;
|
||||
|
||||
comp2 = ChooseSecondComponent();
|
||||
if(comp2 != -1){
|
||||
atomic = RpAtomicClone(m_comps[comp2]);
|
||||
f = RwFrameCreate();
|
||||
RwFrameTransform(f,
|
||||
RwFrameGetMatrix(RpAtomicGetFrame(m_comps[comp2])),
|
||||
rwCOMBINEREPLACE);
|
||||
RpAtomicSetFrame(atomic, f);
|
||||
RpClumpAddAtomic(clump, atomic);
|
||||
RwFrameAddChild(clumpframe, f);
|
||||
}
|
||||
ms_compsUsed[1] = comp2;
|
||||
}else{
|
||||
ms_compsUsed[0] = -1;
|
||||
ms_compsUsed[1] = -1;
|
||||
}
|
||||
return (RwObject*)clump;
|
||||
}
|
||||
|
||||
void
|
||||
CVehicleModelInfo::SetClump(RpClump *clump)
|
||||
{
|
||||
CClumpModelInfo::SetClump(clump);
|
||||
SetAtomicRenderCallbacks();
|
||||
SetFrameIds(ms_vehicleDescs[m_vehicleType]);
|
||||
PreprocessHierarchy();
|
||||
FindEditableMaterialList();
|
||||
m_envMap = nil;
|
||||
SetEnvironmentMap();
|
||||
}
|
||||
|
||||
RwFrame*
|
||||
CVehicleModelInfo::CollapseFramesCB(RwFrame *frame, void *data)
|
||||
{
|
||||
RwFrameForAllChildren(frame, CollapseFramesCB, data);
|
||||
RwFrameForAllObjects(frame, MoveObjectsCB, data);
|
||||
RwFrameDestroy(frame);
|
||||
return frame;
|
||||
}
|
||||
|
||||
RwObject*
|
||||
CVehicleModelInfo::MoveObjectsCB(RwObject *object, void *data)
|
||||
{
|
||||
RpAtomicSetFrame((RpAtomic*)object, (RwFrame*)data);
|
||||
return object;
|
||||
}
|
||||
|
||||
RpAtomic*
|
||||
CVehicleModelInfo::HideDamagedAtomicCB(RpAtomic *atomic, void *data)
|
||||
{
|
||||
if(strstr(GetFrameNodeName(RpAtomicGetFrame(atomic)), "_dam")){
|
||||
RpAtomicSetFlags(atomic, 0);
|
||||
CVisibilityPlugins::SetAtomicFlag(atomic, ATOMIC_FLAG_DAM);
|
||||
}else if(strstr(GetFrameNodeName(RpAtomicGetFrame(atomic)), "_ok"))
|
||||
CVisibilityPlugins::SetAtomicFlag(atomic, ATOMIC_FLAG_OK);
|
||||
return atomic;
|
||||
}
|
||||
|
||||
RpMaterial*
|
||||
CVehicleModelInfo::HasAlphaMaterialCB(RpMaterial *material, void *data)
|
||||
{
|
||||
if(RpMaterialGetColor(material)->alpha != 0xFF){
|
||||
*(bool*)data = true;
|
||||
return nil;
|
||||
}
|
||||
return material;
|
||||
}
|
||||
|
||||
|
||||
RpAtomic*
|
||||
CVehicleModelInfo::SetAtomicRendererCB(RpAtomic *atomic, void *data)
|
||||
{
|
||||
RpClump *clump;
|
||||
char *name;
|
||||
bool alpha;
|
||||
|
||||
clump = (RpClump*)data;
|
||||
name = GetFrameNodeName(RpAtomicGetFrame(atomic));
|
||||
alpha = false;
|
||||
RpGeometryForAllMaterials(RpAtomicGetGeometry(atomic), HasAlphaMaterialCB, &alpha);
|
||||
if(strstr(name, "_hi") || strncmp(name, "extra", 5) == 0){
|
||||
if(alpha || strncmp(name, "windscreen", 10) == 0)
|
||||
CVisibilityPlugins::SetAtomicRenderCallback(atomic, CVisibilityPlugins::RenderVehicleHiDetailAlphaCB);
|
||||
else
|
||||
CVisibilityPlugins::SetAtomicRenderCallback(atomic, CVisibilityPlugins::RenderVehicleHiDetailCB);
|
||||
}else if(strstr(name, "_lo")){
|
||||
RpClumpRemoveAtomic(clump, atomic);
|
||||
RpAtomicDestroy(atomic);
|
||||
return atomic; // BUG: not done by gta
|
||||
}else if(strstr(name, "_vlo"))
|
||||
CVisibilityPlugins::SetAtomicRenderCallback(atomic, CVisibilityPlugins::RenderVehicleReallyLowDetailCB);
|
||||
else
|
||||
CVisibilityPlugins::SetAtomicRenderCallback(atomic, nil);
|
||||
HideDamagedAtomicCB(atomic, nil);
|
||||
return atomic;
|
||||
}
|
||||
|
||||
RpAtomic*
|
||||
CVehicleModelInfo::SetAtomicRendererCB_BigVehicle(RpAtomic *atomic, void *data)
|
||||
{
|
||||
char *name;
|
||||
bool alpha;
|
||||
|
||||
name = GetFrameNodeName(RpAtomicGetFrame(atomic));
|
||||
alpha = false;
|
||||
RpGeometryForAllMaterials(RpAtomicGetGeometry(atomic), HasAlphaMaterialCB, &alpha);
|
||||
if(strstr(name, "_hi") || strncmp(name, "extra", 5) == 0){
|
||||
if(alpha)
|
||||
CVisibilityPlugins::SetAtomicRenderCallback(atomic, CVisibilityPlugins::RenderVehicleHiDetailAlphaCB_BigVehicle);
|
||||
else
|
||||
CVisibilityPlugins::SetAtomicRenderCallback(atomic, CVisibilityPlugins::RenderVehicleHiDetailCB_BigVehicle);
|
||||
}else if(strstr(name, "_lo")){
|
||||
if(alpha)
|
||||
CVisibilityPlugins::SetAtomicRenderCallback(atomic, CVisibilityPlugins::RenderVehicleLowDetailAlphaCB_BigVehicle);
|
||||
else
|
||||
CVisibilityPlugins::SetAtomicRenderCallback(atomic, CVisibilityPlugins::RenderVehicleLowDetailCB_BigVehicle);
|
||||
}else if(strstr(name, "_vlo"))
|
||||
CVisibilityPlugins::SetAtomicRenderCallback(atomic, CVisibilityPlugins::RenderVehicleReallyLowDetailCB_BigVehicle);
|
||||
else
|
||||
CVisibilityPlugins::SetAtomicRenderCallback(atomic, nil);
|
||||
HideDamagedAtomicCB(atomic, nil);
|
||||
return atomic;
|
||||
}
|
||||
|
||||
RpAtomic*
|
||||
CVehicleModelInfo::SetAtomicRendererCB_Train(RpAtomic *atomic, void *data)
|
||||
{
|
||||
char *name;
|
||||
bool alpha;
|
||||
|
||||
name = GetFrameNodeName(RpAtomicGetFrame(atomic));
|
||||
alpha = false;
|
||||
RpGeometryForAllMaterials(RpAtomicGetGeometry(atomic), HasAlphaMaterialCB, &alpha);
|
||||
if(strstr(name, "_hi")){
|
||||
if(alpha)
|
||||
CVisibilityPlugins::SetAtomicRenderCallback(atomic, CVisibilityPlugins::RenderTrainHiDetailAlphaCB);
|
||||
else
|
||||
CVisibilityPlugins::SetAtomicRenderCallback(atomic, CVisibilityPlugins::RenderTrainHiDetailCB);
|
||||
}else if(strstr(name, "_vlo"))
|
||||
CVisibilityPlugins::SetAtomicRenderCallback(atomic, CVisibilityPlugins::RenderVehicleReallyLowDetailCB_BigVehicle);
|
||||
else
|
||||
CVisibilityPlugins::SetAtomicRenderCallback(atomic, nil);
|
||||
HideDamagedAtomicCB(atomic, nil);
|
||||
return atomic;
|
||||
}
|
||||
|
||||
RpAtomic*
|
||||
CVehicleModelInfo::SetAtomicRendererCB_Boat(RpAtomic *atomic, void *data)
|
||||
{
|
||||
RpClump *clump;
|
||||
char *name;
|
||||
|
||||
clump = (RpClump*)data;
|
||||
name = GetFrameNodeName(RpAtomicGetFrame(atomic));
|
||||
if(strcmp(name, "boat_hi") == 0 || strncmp(name, "extra", 5) == 0)
|
||||
CVisibilityPlugins::SetAtomicRenderCallback(atomic, CVisibilityPlugins::RenderVehicleHiDetailCB_Boat);
|
||||
else if(strstr(name, "_hi"))
|
||||
CVisibilityPlugins::SetAtomicRenderCallback(atomic, CVisibilityPlugins::RenderVehicleHiDetailCB);
|
||||
else if(strstr(name, "_lo")){
|
||||
RpClumpRemoveAtomic(clump, atomic);
|
||||
RpAtomicDestroy(atomic);
|
||||
return atomic; // BUG: not done by gta
|
||||
}else if(strstr(name, "_vlo"))
|
||||
CVisibilityPlugins::SetAtomicRenderCallback(atomic, CVisibilityPlugins::RenderVehicleReallyLowDetailCB_BigVehicle);
|
||||
else
|
||||
CVisibilityPlugins::SetAtomicRenderCallback(atomic, nil);
|
||||
HideDamagedAtomicCB(atomic, nil);
|
||||
return atomic;
|
||||
}
|
||||
|
||||
RpAtomic*
|
||||
CVehicleModelInfo::SetAtomicRendererCB_Heli(RpAtomic *atomic, void *data)
|
||||
{
|
||||
CVisibilityPlugins::SetAtomicRenderCallback(atomic, nil);
|
||||
return atomic;
|
||||
}
|
||||
|
||||
void
|
||||
CVehicleModelInfo::SetAtomicRenderCallbacks(void)
|
||||
{
|
||||
switch(m_vehicleType){
|
||||
case VEHICLE_TYPE_TRAIN:
|
||||
RpClumpForAllAtomics(m_clump, SetAtomicRendererCB_Train, nil);
|
||||
break;
|
||||
case VEHICLE_TYPE_HELI:
|
||||
RpClumpForAllAtomics(m_clump, SetAtomicRendererCB_Heli, nil);
|
||||
break;
|
||||
case VEHICLE_TYPE_PLANE:
|
||||
RpClumpForAllAtomics(m_clump, SetAtomicRendererCB_BigVehicle, nil);
|
||||
break;
|
||||
case VEHICLE_TYPE_BOAT:
|
||||
RpClumpForAllAtomics(m_clump, SetAtomicRendererCB_Boat, m_clump);
|
||||
break;
|
||||
default:
|
||||
RpClumpForAllAtomics(m_clump, SetAtomicRendererCB, m_clump);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
RpAtomic*
|
||||
CVehicleModelInfo::SetAtomicFlagCB(RpAtomic *atomic, void *data)
|
||||
{
|
||||
CVisibilityPlugins::SetAtomicFlag(atomic, (int)data);
|
||||
return atomic;
|
||||
}
|
||||
|
||||
RpAtomic*
|
||||
CVehicleModelInfo::ClearAtomicFlagCB(RpAtomic *atomic, void *data)
|
||||
{
|
||||
CVisibilityPlugins::ClearAtomicFlag(atomic, (int)data);
|
||||
return atomic;
|
||||
}
|
||||
|
||||
RwObject*
|
||||
GetOkAndDamagedAtomicCB(RwObject *object, void *data)
|
||||
{
|
||||
RpAtomic *atomic = (RpAtomic*)object;
|
||||
if(CVisibilityPlugins::GetAtomicId(atomic) & ATOMIC_FLAG_OK)
|
||||
((RpAtomic**)data)[0] = atomic;
|
||||
else if(CVisibilityPlugins::GetAtomicId(atomic) & ATOMIC_FLAG_DAM)
|
||||
((RpAtomic**)data)[1] = atomic;
|
||||
return object;
|
||||
}
|
||||
|
||||
void
|
||||
CVehicleModelInfo::PreprocessHierarchy(void)
|
||||
{
|
||||
int32 i;
|
||||
RwObjectNameIdAssocation *desc;
|
||||
RwFrame *f;
|
||||
RpAtomic *atomic;
|
||||
RwV3d *rwvec;
|
||||
|
||||
desc = ms_vehicleDescs[m_vehicleType];
|
||||
m_numDoors = 0;
|
||||
m_numComps = 0;
|
||||
|
||||
for(i = 0; desc[i].name; i++){
|
||||
RwObjectNameAssociation assoc;
|
||||
|
||||
if((desc[i].flags & (VEHICLE_FLAG_COMP|VEHICLE_FLAG_POS)) == 0)
|
||||
continue;
|
||||
assoc.frame = nil;
|
||||
assoc.name = desc[i].name;
|
||||
RwFrameForAllChildren(RpClumpGetFrame(m_clump),
|
||||
FindFrameFromNameWithoutIdCB, &assoc);
|
||||
if(assoc.frame == nil)
|
||||
continue;
|
||||
|
||||
if(desc[i].flags & VEHICLE_FLAG_DOOR)
|
||||
m_numDoors++;
|
||||
|
||||
if(desc[i].flags & VEHICLE_FLAG_POS){
|
||||
f = assoc.frame;
|
||||
rwvec = (RwV3d*)&m_positions[desc[i].hierId];
|
||||
*rwvec = *RwMatrixGetPos(RwFrameGetMatrix(f));
|
||||
for(f = RwFrameGetParent(f); f; f = RwFrameGetParent(f))
|
||||
RwV3dTransformPoints(rwvec, rwvec, 1, RwFrameGetMatrix(f));
|
||||
RwFrameDestroy(assoc.frame);
|
||||
}else{
|
||||
atomic = (RpAtomic*)GetFirstObject(assoc.frame);
|
||||
RpClumpRemoveAtomic(m_clump, atomic);
|
||||
RwFrameRemoveChild(assoc.frame);
|
||||
SetVehicleComponentFlags(assoc.frame, desc[i].flags);
|
||||
m_comps[m_numComps++] = atomic;
|
||||
}
|
||||
}
|
||||
|
||||
for(i = 0; desc[i].name; i++){
|
||||
RwObjectIdAssociation assoc;
|
||||
|
||||
if(desc[i].flags & (VEHICLE_FLAG_COMP|VEHICLE_FLAG_POS))
|
||||
continue;
|
||||
assoc.frame = nil;
|
||||
assoc.id = desc[i].hierId;
|
||||
RwFrameForAllChildren(RpClumpGetFrame(m_clump),
|
||||
FindFrameFromIdCB, &assoc);
|
||||
if(assoc.frame == nil)
|
||||
continue;
|
||||
|
||||
if(desc[i].flags & VEHICLE_FLAG_DOOR)
|
||||
m_numDoors++;
|
||||
|
||||
if(desc[i].flags & VEHICLE_FLAG_COLLAPSE){
|
||||
RpAtomic *okdam[2] = { nil, nil };
|
||||
RwFrameForAllChildren(assoc.frame, CollapseFramesCB, assoc.frame);
|
||||
RwFrameUpdateObjects(assoc.frame);
|
||||
RwFrameForAllObjects(assoc.frame, GetOkAndDamagedAtomicCB, okdam);
|
||||
if(okdam[0] && okdam[1])
|
||||
RpAtomicSetRenderCallBack(okdam[1], RpAtomicGetRenderCallBack(okdam[0]));
|
||||
}
|
||||
|
||||
SetVehicleComponentFlags(assoc.frame, desc[i].flags);
|
||||
|
||||
if(desc[i].flags & VEHICLE_FLAG_ADD_WHEEL){
|
||||
if(m_wheelId == -1)
|
||||
RwFrameDestroy(assoc.frame);
|
||||
else{
|
||||
RwV3d scale;
|
||||
atomic = (RpAtomic*)CModelInfo::GetModelInfo(m_wheelId)->CreateInstance();
|
||||
RwFrameDestroy(RpAtomicGetFrame(atomic));
|
||||
RpAtomicSetFrame(atomic, assoc.frame);
|
||||
RpClumpAddAtomic(m_clump, atomic);
|
||||
CVisibilityPlugins::SetAtomicRenderCallback(atomic,
|
||||
CVisibilityPlugins::RenderWheelAtomicCB);
|
||||
scale.x = m_wheelScale;
|
||||
scale.y = m_wheelScale;
|
||||
scale.z = m_wheelScale;
|
||||
RwFrameScale(assoc.frame, &scale, rwCOMBINEPRECONCAT);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define COMPRULE_RULE(comprule) (((comprule) >> 12) & 0xF)
|
||||
#define COMPRULE_COMPS(comprule) ((comprule) & 0xFFF)
|
||||
#define COMPRULE_COMPN(comps, n) (((comps) >> 4*(n)) & 0xF)
|
||||
#define COMPRULE2_RULE(comprule) (((comprule) >> (12+16)) & 0xF)
|
||||
#define COMPRULE2_COMPS(comprule) ((comprule >> 16) & 0xFFF)
|
||||
#define COMPRULE2_COMPN(comps, n) (((comps >> 16) >> 4*(n)) & 0xF)
|
||||
|
||||
bool
|
||||
IsValidCompRule(int rule)
|
||||
{
|
||||
if(rule == 2)
|
||||
return CWeather::OldWeatherType == WEATHER_RAINY ||
|
||||
CWeather::NewWeatherType == WEATHER_RAINY;
|
||||
return true;
|
||||
}
|
||||
|
||||
int32
|
||||
CountCompsInRule(int comps)
|
||||
{
|
||||
int32 n;
|
||||
for(n = 0; comps != 0; comps >>= 4)
|
||||
if((comps & 0xF) != 0xF)
|
||||
n++;
|
||||
return n;
|
||||
}
|
||||
|
||||
int32
|
||||
ChooseComponent(int32 rule, int32 comps)
|
||||
{
|
||||
int32 n;
|
||||
switch(rule){
|
||||
// identical cases....
|
||||
case 1:
|
||||
n = CGeneral::GetRandomNumberInRange(0, CountCompsInRule(comps));
|
||||
return COMPRULE_COMPN(comps, n);
|
||||
case 2:
|
||||
// only valid in rain
|
||||
n = CGeneral::GetRandomNumberInRange(0, CountCompsInRule(comps));
|
||||
return COMPRULE_COMPN(comps, n);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int32
|
||||
GetListOfComponentsNotUsedByRules(uint32 comprules, int32 numComps, int32 *comps)
|
||||
{
|
||||
int32 i, n;
|
||||
int32 unused[6] = { 0, 1, 2, 3, 4, 5 };
|
||||
|
||||
// first comprule
|
||||
if(COMPRULE_RULE(comprules) && IsValidCompRule(COMPRULE_RULE(comprules)))
|
||||
for(i = 0; i < 3; i++){
|
||||
n = COMPRULE_COMPN(comprules, i);
|
||||
if(n != 0xF)
|
||||
unused[n] = 0xF;
|
||||
}
|
||||
// second comprule
|
||||
comprules >>= 16;
|
||||
if(COMPRULE_RULE(comprules) && IsValidCompRule(COMPRULE_RULE(comprules)))
|
||||
for(i = 0; i < 3; i++){
|
||||
n = COMPRULE_COMPN(comprules, i);
|
||||
if(n != 0xF)
|
||||
unused[n] = 0xF;
|
||||
}
|
||||
|
||||
n = 0;
|
||||
for(i = 0; i < numComps; i++)
|
||||
if(unused[i] != 0xF)
|
||||
comps[n++] = unused[i];
|
||||
return n;
|
||||
}
|
||||
|
||||
int32 wheelIds[] = { CAR_WHEEL_LF, CAR_WHEEL_LB, CAR_WHEEL_RF, CAR_WHEEL_RB };
|
||||
|
||||
void
|
||||
CVehicleModelInfo::GetWheelPosn(int32 n, CVector &pos)
|
||||
{
|
||||
RwMatrix *m = RwFrameGetMatrix(GetFrameFromId(m_clump, wheelIds[n]));
|
||||
pos.x = RwMatrixGetPos(m)->x;
|
||||
pos.y = RwMatrixGetPos(m)->y;
|
||||
pos.z = RwMatrixGetPos(m)->z;
|
||||
}
|
||||
|
||||
|
||||
int32
|
||||
CVehicleModelInfo::ChooseComponent(void)
|
||||
{
|
||||
int32 comp;
|
||||
int32 comps[8];
|
||||
int32 n;
|
||||
|
||||
comp = -1;
|
||||
if(ms_compsToUse[0] == -2){
|
||||
if(COMPRULE_RULE(m_compRules) && IsValidCompRule(COMPRULE_RULE(m_compRules)))
|
||||
comp = ::ChooseComponent(COMPRULE_RULE(m_compRules), COMPRULE_COMPS(m_compRules));
|
||||
else if(CGeneral::GetRandomNumberInRange(0, 3) < 2){
|
||||
n = GetListOfComponentsNotUsedByRules(m_compRules, m_numComps, comps);
|
||||
if(n)
|
||||
comp = comps[(int)CGeneral::GetRandomNumberInRange(0, n)];
|
||||
}
|
||||
}else{
|
||||
comp = ms_compsToUse[0];
|
||||
ms_compsToUse[0] = -2;
|
||||
}
|
||||
return comp;
|
||||
}
|
||||
|
||||
int32
|
||||
CVehicleModelInfo::ChooseSecondComponent(void)
|
||||
{
|
||||
int32 comp;
|
||||
int32 comps[8];
|
||||
int32 n;
|
||||
|
||||
comp = -1;
|
||||
if(ms_compsToUse[1] == -2){
|
||||
if(COMPRULE2_RULE(m_compRules) && IsValidCompRule(COMPRULE2_RULE(m_compRules)))
|
||||
comp = ::ChooseComponent(COMPRULE2_RULE(m_compRules), COMPRULE2_COMPS(m_compRules));
|
||||
else if(COMPRULE_RULE(m_compRules) && IsValidCompRule(COMPRULE_RULE(m_compRules)) &&
|
||||
CGeneral::GetRandomNumberInRange(0, 3) < 2){
|
||||
|
||||
n = GetListOfComponentsNotUsedByRules(m_compRules, m_numComps, comps);
|
||||
if(n)
|
||||
comp = comps[(int)CGeneral::GetRandomNumberInRange(0, n)];
|
||||
}
|
||||
}else{
|
||||
comp = ms_compsToUse[1];
|
||||
ms_compsToUse[1] = -2;
|
||||
}
|
||||
return comp;
|
||||
}
|
||||
|
||||
struct editableMatCBData
|
||||
{
|
||||
CVehicleModelInfo *vehicle;
|
||||
int32 numMats1;
|
||||
int32 numMats2;
|
||||
};
|
||||
|
||||
RpMaterial*
|
||||
CVehicleModelInfo::GetEditableMaterialListCB(RpMaterial *material, void *data)
|
||||
{
|
||||
static RwRGBA white = { 255, 255, 255, 255 };
|
||||
RwRGBA *col;
|
||||
editableMatCBData *cbdata;
|
||||
|
||||
cbdata = (editableMatCBData*)data;
|
||||
col = RpMaterialGetColor(material);
|
||||
if(col->red == 0x3C && col->green == 0xFF && col->blue == 0){
|
||||
cbdata->vehicle->m_materials1[cbdata->numMats1++] = material;
|
||||
RpMaterialSetColor(material, &white);
|
||||
}else if(col->red == 0xFF && col->green == 0 && col->blue == 0xAF){
|
||||
cbdata->vehicle->m_materials2[cbdata->numMats2++] = material;
|
||||
RpMaterialSetColor(material, &white);
|
||||
}
|
||||
return material;
|
||||
}
|
||||
|
||||
RpAtomic*
|
||||
CVehicleModelInfo::GetEditableMaterialListCB(RpAtomic *atomic, void *data)
|
||||
{
|
||||
RpGeometryForAllMaterials(RpAtomicGetGeometry(atomic), GetEditableMaterialListCB, data);
|
||||
return atomic;
|
||||
}
|
||||
|
||||
void
|
||||
CVehicleModelInfo::FindEditableMaterialList(void)
|
||||
{
|
||||
editableMatCBData cbdata;
|
||||
int32 i;
|
||||
|
||||
cbdata.vehicle = this;
|
||||
cbdata.numMats1 = 0;
|
||||
cbdata.numMats2 = 0;
|
||||
RpClumpForAllAtomics(m_clump, GetEditableMaterialListCB, &cbdata);
|
||||
for(i = 0; i < m_numComps; i++)
|
||||
GetEditableMaterialListCB(m_comps[i], &cbdata);
|
||||
m_materials1[cbdata.numMats1] = nil;
|
||||
m_materials2[cbdata.numMats2] = nil;
|
||||
m_currentColour1 = -1;
|
||||
m_currentColour2 = -1;
|
||||
}
|
||||
|
||||
void
|
||||
CVehicleModelInfo::SetVehicleColour(uint8 c1, uint8 c2)
|
||||
{
|
||||
RwRGBA col, *colp;
|
||||
RwTexture *coltex;
|
||||
RpMaterial **matp;
|
||||
|
||||
if(c1 != m_currentColour1){
|
||||
col = ms_vehicleColourTable[c1];
|
||||
coltex = ms_colourTextureTable[c1];
|
||||
for(matp = m_materials1; *matp; matp++){
|
||||
if(RpMaterialGetTexture(*matp) && RpMaterialGetTexture(*matp)->name[0] != '@'){
|
||||
colp = RpMaterialGetColor(*matp);
|
||||
colp->red = col.red;
|
||||
colp->green = col.green;
|
||||
colp->blue = col.blue;
|
||||
}else
|
||||
RpMaterialSetTexture(*matp, coltex);
|
||||
}
|
||||
m_currentColour1 = c1;
|
||||
}
|
||||
|
||||
if(c2 != m_currentColour2){
|
||||
col = ms_vehicleColourTable[c2];
|
||||
coltex = ms_colourTextureTable[c2];
|
||||
for(matp = m_materials2; *matp; matp++){
|
||||
if(RpMaterialGetTexture(*matp) && RpMaterialGetTexture(*matp)->name[0] != '@'){
|
||||
colp = RpMaterialGetColor(*matp);
|
||||
colp->red = col.red;
|
||||
colp->green = col.green;
|
||||
colp->blue = col.blue;
|
||||
}else
|
||||
RpMaterialSetTexture(*matp, coltex);
|
||||
}
|
||||
m_currentColour2 = c2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
RpMaterial*
|
||||
CVehicleModelInfo::HasSpecularMaterialCB(RpMaterial *material, void *data)
|
||||
{
|
||||
if(RpMaterialGetSurfaceProperties(material)->specular <= 0.0f)
|
||||
return material;
|
||||
*(bool*)data = true;
|
||||
return nil;
|
||||
}
|
||||
|
||||
RpMaterial*
|
||||
CVehicleModelInfo::SetEnvironmentMapCB(RpMaterial *material, void *data)
|
||||
{
|
||||
float spec;
|
||||
|
||||
spec = RpMaterialGetSurfaceProperties(material)->specular;
|
||||
if(spec <= 0.0f)
|
||||
RpMatFXMaterialSetEffects(material, rpMATFXEFFECTNULL);
|
||||
else{
|
||||
if(RpMaterialGetTexture(material) == 0)
|
||||
RpMaterialSetTexture(material, gpWhiteTexture);
|
||||
RpMatFXMaterialSetEffects(material, rpMATFXEFFECTENVMAP);
|
||||
spec *= 0.5f; // Tone down a bit for PC
|
||||
RpMatFXMaterialSetupEnvMap(material, (RwTexture*)data, pMatFxIdentityFrame, false, spec);
|
||||
}
|
||||
return material;
|
||||
}
|
||||
|
||||
RpAtomic*
|
||||
CVehicleModelInfo::SetEnvironmentMapCB(RpAtomic *atomic, void *data)
|
||||
{
|
||||
bool hasSpec;
|
||||
RpGeometry *geo;
|
||||
|
||||
geo = RpAtomicGetGeometry(atomic);
|
||||
hasSpec = 0;
|
||||
RpGeometryForAllMaterials(geo, HasSpecularMaterialCB, &hasSpec);
|
||||
if(hasSpec){
|
||||
RpGeometryForAllMaterials(geo, SetEnvironmentMapCB, data);
|
||||
RpGeometrySetFlags(geo, RpGeometryGetFlags(geo) | rpGEOMETRYMODULATEMATERIALCOLOR);
|
||||
RpMatFXAtomicEnableEffects(atomic);
|
||||
// PS2 sets of PS2Manager lighting CB here
|
||||
}
|
||||
return atomic;
|
||||
}
|
||||
|
||||
void
|
||||
CVehicleModelInfo::SetEnvironmentMap(void)
|
||||
{
|
||||
CSimpleModelInfo *wheelmi;
|
||||
int32 i;
|
||||
|
||||
if(pMatFxIdentityFrame == nil){
|
||||
pMatFxIdentityFrame = RwFrameCreate();
|
||||
RwMatrixSetIdentity(RwFrameGetMatrix(pMatFxIdentityFrame));
|
||||
RwFrameUpdateObjects(pMatFxIdentityFrame);
|
||||
RwFrameGetLTM(pMatFxIdentityFrame);
|
||||
}
|
||||
|
||||
if(m_envMap != ms_pEnvironmentMaps[0]){
|
||||
m_envMap = ms_pEnvironmentMaps[0];
|
||||
RpClumpForAllAtomics(m_clump, SetEnvironmentMapCB, m_envMap);
|
||||
if(m_wheelId != -1){
|
||||
wheelmi = (CSimpleModelInfo*)CModelInfo::GetModelInfo(m_wheelId);
|
||||
for(i = 0; i < wheelmi->m_numAtomics; i++)
|
||||
SetEnvironmentMapCB(wheelmi->m_atomics[i], m_envMap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CVehicleModelInfo::LoadEnvironmentMaps(void)
|
||||
{
|
||||
char *texnames[] = {
|
||||
"reflection01", // only one used
|
||||
"reflection02",
|
||||
"reflection03",
|
||||
"reflection04",
|
||||
"reflection05",
|
||||
"reflection06",
|
||||
};
|
||||
int32 txdslot;
|
||||
int32 i;
|
||||
|
||||
txdslot = CTxdStore::FindTxdSlot("particle");
|
||||
CTxdStore::PushCurrentTxd();
|
||||
CTxdStore::SetCurrentTxd(txdslot);
|
||||
for(i = 0; i < NUM_VEHICLE_ENVMAPS; i++){
|
||||
ms_pEnvironmentMaps[i] = RwTextureRead(texnames[i], nil);
|
||||
RwTextureSetFilterMode(ms_pEnvironmentMaps[i], rwFILTERLINEAR);
|
||||
}
|
||||
if(gpWhiteTexture == nil){
|
||||
gpWhiteTexture = RwTextureRead("white", nil);
|
||||
gpWhiteTexture->name[0] = '@';
|
||||
RwTextureSetFilterMode(gpWhiteTexture, rwFILTERLINEAR);
|
||||
}
|
||||
CTxdStore::PopCurrentTxd();
|
||||
}
|
||||
|
||||
void
|
||||
CVehicleModelInfo::ShutdownEnvironmentMaps(void)
|
||||
{
|
||||
int32 i;
|
||||
|
||||
// ignoring "initialised" as that's a PS2 thing only
|
||||
RwTextureDestroy(gpWhiteTexture);
|
||||
gpWhiteTexture = nil;
|
||||
for(i = 0; i < NUM_VEHICLE_ENVMAPS; i++)
|
||||
if(ms_pEnvironmentMaps[i])
|
||||
RwTextureDestroy(ms_pEnvironmentMaps[i]);
|
||||
RwFrameDestroy(pMatFxIdentityFrame);
|
||||
pMatFxIdentityFrame = nil;
|
||||
}
|
||||
|
||||
STARTPATCHES
|
||||
InjectHook(0x51FDC0, &CVehicleModelInfo::DeleteRwObject_, PATCH_JUMP);
|
||||
InjectHook(0x51FCB0, &CVehicleModelInfo::CreateInstance_, PATCH_JUMP);
|
||||
InjectHook(0x51FC60, &CVehicleModelInfo::SetClump_, PATCH_JUMP);
|
||||
|
||||
InjectHook(0x51FE10, &CVehicleModelInfo::CollapseFramesCB, PATCH_JUMP);
|
||||
InjectHook(0x51FE50, &CVehicleModelInfo::MoveObjectsCB, PATCH_JUMP);
|
||||
InjectHook(0x51FE70, &CVehicleModelInfo::HideDamagedAtomicCB, PATCH_JUMP);
|
||||
InjectHook(0x51FEF0, &CVehicleModelInfo::HasAlphaMaterialCB, PATCH_JUMP);
|
||||
|
||||
InjectHook(0x51FF10, &CVehicleModelInfo::SetAtomicRendererCB, PATCH_JUMP);
|
||||
InjectHook(0x520030, &CVehicleModelInfo::SetAtomicRendererCB_BigVehicle, PATCH_JUMP);
|
||||
InjectHook(0x520230, &CVehicleModelInfo::SetAtomicRendererCB_Train, PATCH_JUMP);
|
||||
InjectHook(0x520120, &CVehicleModelInfo::SetAtomicRendererCB_Boat, PATCH_JUMP);
|
||||
InjectHook(0x520210, &CVehicleModelInfo::SetAtomicRendererCB_Heli, PATCH_JUMP);
|
||||
InjectHook(0x5202C0, &CVehicleModelInfo::SetAtomicRenderCallbacks, PATCH_JUMP);
|
||||
|
||||
InjectHook(0x520340, &CVehicleModelInfo::SetAtomicFlagCB, PATCH_JUMP);
|
||||
InjectHook(0x520360, &CVehicleModelInfo::ClearAtomicFlagCB, PATCH_JUMP);
|
||||
|
||||
InjectHook(0x5204D0, &CVehicleModelInfo::PreprocessHierarchy, PATCH_JUMP);
|
||||
|
||||
InjectHook(0x520840, &CVehicleModelInfo::GetWheelPosn, PATCH_JUMP);
|
||||
|
||||
InjectHook(0x520880, IsValidCompRule, PATCH_JUMP);
|
||||
InjectHook(0x520990, CountCompsInRule, PATCH_JUMP);
|
||||
InjectHook(0x5209C0, ChooseComponent, PATCH_JUMP);
|
||||
InjectHook(0x5208C0, GetListOfComponentsNotUsedByRules, PATCH_JUMP);
|
||||
InjectHook(0x520AB0, &CVehicleModelInfo::ChooseComponent, PATCH_JUMP);
|
||||
InjectHook(0x520BE0, &CVehicleModelInfo::ChooseSecondComponent, PATCH_JUMP);
|
||||
|
||||
InjectHook(0x520DC0, (RpAtomic *(*)(RpAtomic*, void*))CVehicleModelInfo::GetEditableMaterialListCB, PATCH_JUMP);
|
||||
InjectHook(0x520D30, (RpMaterial *(*)(RpMaterial*, void*))CVehicleModelInfo::GetEditableMaterialListCB, PATCH_JUMP);
|
||||
InjectHook(0x520DE0, &CVehicleModelInfo::FindEditableMaterialList, PATCH_JUMP);
|
||||
InjectHook(0x520E70, &CVehicleModelInfo::SetVehicleColour, PATCH_JUMP);
|
||||
|
||||
InjectHook(0x521820, (RpAtomic *(*)(RpAtomic*, void*))CVehicleModelInfo::SetEnvironmentMapCB, PATCH_JUMP);
|
||||
InjectHook(0x5217A0, (RpMaterial *(*)(RpMaterial*, void*))CVehicleModelInfo::SetEnvironmentMapCB, PATCH_JUMP);
|
||||
InjectHook(0x521770, CVehicleModelInfo::HasSpecularMaterialCB, PATCH_JUMP);
|
||||
InjectHook(0x521890, &CVehicleModelInfo::SetEnvironmentMap, PATCH_JUMP);
|
||||
InjectHook(0x521680, CVehicleModelInfo::LoadEnvironmentMaps, PATCH_JUMP);
|
||||
InjectHook(0x521720, CVehicleModelInfo::ShutdownEnvironmentMaps, PATCH_JUMP);
|
||||
ENDPATCHES
|
115
src/modelinfo/VehicleModelInfo.h
Normal file
115
src/modelinfo/VehicleModelInfo.h
Normal file
@ -0,0 +1,115 @@
|
||||
#pragma once
|
||||
|
||||
#include "ClumpModelInfo.h"
|
||||
|
||||
enum {
|
||||
NUM_VEHICLE_POSITIONS = 10,
|
||||
NUM_FIRST_MATERIALS = 26,
|
||||
NUM_SECOND_MATERIALS = 26,
|
||||
NUM_VEHICLE_COLOURS = 8,
|
||||
NUM_VEHICLE_ENVMAPS = 1
|
||||
};
|
||||
|
||||
enum {
|
||||
ATOMIC_FLAG_OK = 0x1,
|
||||
ATOMIC_FLAG_DAM = 0x2,
|
||||
ATOMIC_FLAG_LEFT = 0x4,
|
||||
ATOMIC_FLAG_RIGHT = 0x8,
|
||||
ATOMIC_FLAG_FRONT = 0x10,
|
||||
ATOMIC_FLAG_REAR = 0x20,
|
||||
ATOMIC_FLAG_DRAWLAST = 0x40,
|
||||
ATOMIC_FLAG_WINDSCREEN = 0x80,
|
||||
ATOMIC_FLAG_ANGLECULL = 0x100,
|
||||
ATOMIC_FLAG_REARDOOR = 0x200,
|
||||
ATOMIC_FLAG_FRONTDOOR = 0x400,
|
||||
ATOMIC_FLAG_NOCULL = 0x800,
|
||||
};
|
||||
|
||||
enum {
|
||||
VEHICLE_TYPE_CAR,
|
||||
VEHICLE_TYPE_BOAT,
|
||||
VEHICLE_TYPE_TRAIN,
|
||||
VEHICLE_TYPE_HELI,
|
||||
VEHICLE_TYPE_PLANE,
|
||||
VEHICLE_TYPE_BIKE,
|
||||
NUM_VEHICLE_TYPES
|
||||
};
|
||||
|
||||
class CVehicleModelInfo : public CClumpModelInfo
|
||||
{
|
||||
public:
|
||||
uint8 m_lastColour1;
|
||||
uint8 m_lastColour2;
|
||||
char m_gameName[32];
|
||||
int32 m_vehicleType;
|
||||
int32 m_wheelId;
|
||||
float m_wheelScale;
|
||||
int32 m_numDoors;
|
||||
int32 m_handlingId;
|
||||
int32 m_vehicleClass;
|
||||
int32 m_level;
|
||||
CVector m_positions[NUM_VEHICLE_POSITIONS];
|
||||
uint32 m_compRules;
|
||||
float m_bikeSteerAngle;
|
||||
RpMaterial *m_materials1[NUM_FIRST_MATERIALS];
|
||||
RpMaterial *m_materials2[NUM_SECOND_MATERIALS];
|
||||
uint8 m_colours1[NUM_VEHICLE_COLOURS];
|
||||
uint8 m_colours2[NUM_VEHICLE_COLOURS];
|
||||
uint8 m_numColours;
|
||||
uint8 m_bLastColorVariation; //
|
||||
uint8 m_currentColour1;
|
||||
uint8 m_currentColour2;
|
||||
RwTexture *m_envMap;
|
||||
RpAtomic *m_comps[6];
|
||||
int32 m_numComps;
|
||||
|
||||
static int8 *ms_compsToUse; // [2];
|
||||
static int8 *ms_compsUsed; // [2];
|
||||
static RwTexture **ms_pEnvironmentMaps; // [NUM_VEHICLE_ENVMAPS]
|
||||
static RwRGBA *ms_vehicleColourTable; // [256]
|
||||
static RwTexture **ms_colourTextureTable; // [256]
|
||||
static RwObjectNameIdAssocation *ms_vehicleDescs[NUM_VEHICLE_TYPES];
|
||||
|
||||
CVehicleModelInfo(void);
|
||||
void DeleteRwObject(void);
|
||||
RwObject *CreateInstance(void);
|
||||
void SetClump(RpClump *);
|
||||
|
||||
static RwFrame *CollapseFramesCB(RwFrame *frame, void *data);
|
||||
static RwObject *MoveObjectsCB(RwObject *object, void *data);
|
||||
static RpAtomic *HideDamagedAtomicCB(RpAtomic *atomic, void *data);
|
||||
static RpMaterial *HasAlphaMaterialCB(RpMaterial *material, void *data);
|
||||
|
||||
static RpAtomic *SetAtomicRendererCB(RpAtomic *atomic, void *data);
|
||||
static RpAtomic *SetAtomicRendererCB_BigVehicle(RpAtomic *atomic, void *data);
|
||||
static RpAtomic *SetAtomicRendererCB_Train(RpAtomic *atomic, void *data);
|
||||
static RpAtomic *SetAtomicRendererCB_Boat(RpAtomic *atomic, void *data);
|
||||
static RpAtomic *SetAtomicRendererCB_Heli(RpAtomic *atomic, void *data);
|
||||
void SetAtomicRenderCallbacks(void);
|
||||
|
||||
static RpAtomic *SetAtomicFlagCB(RpAtomic *atomic, void *data);
|
||||
static RpAtomic *ClearAtomicFlagCB(RpAtomic *atomic, void *data);
|
||||
void SetVehicleComponentFlags(RwFrame *frame, uint32 flags);
|
||||
void PreprocessHierarchy(void);
|
||||
void GetWheelPosn(int32 n, CVector &pos);
|
||||
|
||||
int32 ChooseComponent(void);
|
||||
int32 ChooseSecondComponent(void);
|
||||
|
||||
static RpMaterial *GetEditableMaterialListCB(RpMaterial *material, void *data);
|
||||
static RpAtomic *GetEditableMaterialListCB(RpAtomic *atomic, void *data);
|
||||
void FindEditableMaterialList(void);
|
||||
void SetVehicleColour(uint8 c1, uint8 c2);
|
||||
|
||||
static RpAtomic *SetEnvironmentMapCB(RpAtomic *atomic, void *data);
|
||||
static RpMaterial *SetEnvironmentMapCB(RpMaterial *material, void *data);
|
||||
static RpMaterial *HasSpecularMaterialCB(RpMaterial *material, void *data);
|
||||
void SetEnvironmentMap(void);
|
||||
static void LoadEnvironmentMaps(void);
|
||||
static void ShutdownEnvironmentMaps(void);
|
||||
|
||||
void DeleteRwObject_(void) { this->CVehicleModelInfo::DeleteRwObject(); }
|
||||
RwObject *CreateInstance_(void) { return this->CVehicleModelInfo::CreateInstance(); }
|
||||
void SetClump_(RpClump *clump) { this->CVehicleModelInfo::SetClump(clump); }
|
||||
};
|
||||
static_assert(sizeof(CVehicleModelInfo) == 0x1F8, "CVehicleModelInfo: error");
|
Reference in New Issue
Block a user