1
0
Fork 0
mirror of https://git.rip/DMCA_FUCKER/re3.git synced 2024-12-23 20:10:00 +00:00

CPedModelInfo

This commit is contained in:
aap 2020-05-10 13:08:02 +02:00
parent 058690aad7
commit f7300c7a27
7 changed files with 44 additions and 344 deletions

View file

@ -368,13 +368,7 @@ CAnimViewer::Update(void)
} else { } else {
// Originally it was GetPad(1)->LeftShoulder2 // Originally it was GetPad(1)->LeftShoulder2
if (pad->NewState.Triangle) { if (pad->NewState.Triangle) {
#ifdef PED_SKIN ((CPedModelInfo *)CModelInfo::GetModelInfo(pTarget->GetModelIndex()))->AnimatePedColModelSkinned(pTarget->GetClump());
if(IsClumpSkinned(pTarget->GetClump()))
((CPedModelInfo *)CModelInfo::GetModelInfo(pTarget->GetModelIndex()))->AnimatePedColModelSkinned(pTarget->GetClump());
else
#endif
CPedModelInfo::AnimatePedColModel(((CPedModelInfo *)CModelInfo::GetModelInfo(pTarget->GetModelIndex()))->GetHitColModel(),
RpClumpGetFrame(pTarget->GetClump()));
AsciiToUnicode("Ped Col model will be animated as long as you hold the button", gUString); AsciiToUnicode("Ped Col model will be animated as long as you hold the button", gUString);
CMessages::AddMessage(gUString, 100, 0); CMessages::AddMessage(gUString, 100, 0);
} }

View file

@ -443,14 +443,6 @@ CFileLoader::LoadClumpFile(RwStream *stream, uint32 id)
return false; return false;
mi = (CClumpModelInfo*)CModelInfo::GetModelInfo(id); mi = (CClumpModelInfo*)CModelInfo::GetModelInfo(id);
mi->SetClump(clump); mi->SetClump(clump);
if (mi->GetModelType() == MITYPE_PED && id != 0 && RwStreamFindChunk(stream, rwID_CLUMP, nil, nil)) {
// Read LOD ped
clump = RpClumpStreamRead(stream);
if(clump){
((CPedModelInfo*)mi)->SetLowDetailClump(clump);
RpClumpDestroy(clump);
}
}
return true; return true;
} }

View file

@ -339,11 +339,8 @@ CWorld::ProcessLineOfSightSectorList(CPtrList &list, const CColLine &line, CColP
if(e->IsPed()) { if(e->IsPed()) {
if(e->bUsesCollision || deadPeds && ((CPed *)e)->m_nPedState == PED_DEAD) { if(e->bUsesCollision || deadPeds && ((CPed *)e)->m_nPedState == PED_DEAD) {
#ifdef PED_SKIN colmodel = ((CPedModelInfo *)CModelInfo::GetModelInfo(e->GetModelIndex()))->AnimatePedColModelSkinned(e->GetClump());
if(IsClumpSkinned(e->GetClump())) /* this should all be gone, right?
colmodel = ((CPedModelInfo *)CModelInfo::GetModelInfo(e->GetModelIndex()))->AnimatePedColModelSkinned(e->GetClump());
else
#endif
if(((CPed *)e)->UseGroundColModel()) if(((CPed *)e)->UseGroundColModel())
colmodel = &CTempColModels::ms_colModelPedGroundHit; colmodel = &CTempColModels::ms_colModelPedGroundHit;
else else
@ -357,8 +354,10 @@ CWorld::ProcessLineOfSightSectorList(CPtrList &list, const CColLine &line, CColP
((CPedModelInfo *)CModelInfo::GetModelInfo(e->GetModelIndex())) ((CPedModelInfo *)CModelInfo::GetModelInfo(e->GetModelIndex()))
->GetHitColModel(); ->GetHitColModel();
#endif #endif
*/
} else } else
colmodel = nil; colmodel = nil;
} else if(e->bUsesCollision) } else if(e->bUsesCollision)
colmodel = CModelInfo::GetModelInfo(e->GetModelIndex())->GetColModel(); colmodel = CModelInfo::GetModelInfo(e->GetModelIndex())->GetColModel();

View file

@ -9,33 +9,18 @@
#include "VisibilityPlugins.h" #include "VisibilityPlugins.h"
#include "ModelInfo.h" #include "ModelInfo.h"
//--MIAMI: file done
void void
CPedModelInfo::DeleteRwObject(void) CPedModelInfo::DeleteRwObject(void)
{ {
CClumpModelInfo::DeleteRwObject();
if(m_hitColModel) if(m_hitColModel)
delete m_hitColModel; delete m_hitColModel;
m_hitColModel = nil; m_hitColModel = nil;
#ifdef PED_SKIN
RwFrame *frame;
if(m_head){
frame = RpAtomicGetFrame(m_head);
RpAtomicDestroy(m_head);
RwFrameDestroy(frame);
}
if(m_lhand){
frame = RpAtomicGetFrame(m_lhand);
RpAtomicDestroy(m_lhand);
RwFrameDestroy(frame);
}
if(m_rhand){
frame = RpAtomicGetFrame(m_rhand);
RpAtomicDestroy(m_rhand);
RwFrameDestroy(frame);
}
#endif
CClumpModelInfo::DeleteRwObject(); // PC calls this first
} }
// leftover...
RwObjectNameIdAssocation CPedModelInfo::m_pPedIds[PED_NODE_MAX] = { RwObjectNameIdAssocation CPedModelInfo::m_pPedIds[PED_NODE_MAX] = {
{ "Smid", PED_MID, 0, }, // that is strange... { "Smid", PED_MID, 0, }, // that is strange...
{ "Shead", PED_HEAD, 0, }, { "Shead", PED_HEAD, 0, },
@ -51,131 +36,16 @@ RwObjectNameIdAssocation CPedModelInfo::m_pPedIds[PED_NODE_MAX] = {
{ nil, 0, 0, }, { nil, 0, 0, },
}; };
#ifdef PED_SKIN
struct LimbCBarg
{
CPedModelInfo *mi;
RpClump *clump;
int32 frameIDs[3];
};
RpAtomic*
CPedModelInfo::findLimbsCb(RpAtomic *atomic, void *data)
{
LimbCBarg *limbs = (LimbCBarg*)data;
RwFrame *frame = RpAtomicGetFrame(atomic);
const char *name = GetFrameNodeName(frame);
if(CGeneral::faststricmp(name, "Shead01") == 0){
limbs->frameIDs[0] = RpHAnimFrameGetID(frame);
limbs->mi->m_head = atomic;
RpClumpRemoveAtomic(limbs->clump, atomic);
RwFrameRemoveChild(frame);
}else if(CGeneral::faststricmp(name, "SLhand01") == 0){
limbs->frameIDs[1] = RpHAnimFrameGetID(frame);
limbs->mi->m_lhand = atomic;
RpClumpRemoveAtomic(limbs->clump, atomic);
RwFrameRemoveChild(frame);
}else if(CGeneral::faststricmp(name, "SRhand01") == 0){
limbs->frameIDs[2] = RpHAnimFrameGetID(frame);
limbs->mi->m_rhand = atomic;
RpClumpRemoveAtomic(limbs->clump, atomic);
RwFrameRemoveChild(frame);
}
return atomic;
}
#endif
void void
CPedModelInfo::SetClump(RpClump *clump) CPedModelInfo::SetClump(RpClump *clump)
{ {
#ifdef PED_SKIN
// CB has to be set here before atomics are detached from clump
if(strncmp(GetName(), "player", 7) == 0)
RpClumpForAllAtomics(clump, SetAtomicRendererCB, (void*)CVisibilityPlugins::RenderPlayerCB);
if(IsClumpSkinned(clump)){
LimbCBarg limbs = { this, clump, { 0, 0, 0 } };
RpClumpForAllAtomics(clump, findLimbsCb, &limbs);
}
CClumpModelInfo::SetClump(clump); CClumpModelInfo::SetClump(clump);
SetFrameIds(m_pPedIds); SetFrameIds(m_pPedIds); // not needed in VC actually
if(m_hitColModel == nil && !IsClumpSkinned(clump))
CreateHitColModel();
// And again because CClumpModelInfo resets it
if(strncmp(GetName(), "player", 7) == 0)
RpClumpForAllAtomics(m_clump, SetAtomicRendererCB, (void*)CVisibilityPlugins::RenderPlayerCB);
else if(IsClumpSkinned(clump))
// skinned peds have no low detail version, so they don't have the right render Cb
RpClumpForAllAtomics(m_clump, SetAtomicRendererCB, (void*)CVisibilityPlugins::RenderPedCB);
#else
CClumpModelInfo::SetClump(clump);
SetFrameIds(m_pPedIds);
if(m_hitColModel == nil) if(m_hitColModel == nil)
CreateHitColModel(); CreateHitColModelSkinned(clump);
if(strncmp(GetName(), "player", 7) == 0) RpClumpForAllAtomics(m_clump, SetAtomicRendererCB, (void*)CVisibilityPlugins::RenderPedCB);
if(strcmp(GetName(), "player") == 0)
RpClumpForAllAtomics(m_clump, SetAtomicRendererCB, (void*)CVisibilityPlugins::RenderPlayerCB); RpClumpForAllAtomics(m_clump, SetAtomicRendererCB, (void*)CVisibilityPlugins::RenderPlayerCB);
#endif
}
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(CGeneral::faststricmp(GetFrameNodeName(frame)+1, assoc->name+1)){
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, (void*)CVisibilityPlugins::RenderPedHiDetailCB);
RpClumpForAllAtomics(lodclump, SetAtomicRendererCB, (void*)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 struct ColNodeInfo
@ -201,114 +71,6 @@ ColNodeInfo m_pColNodeInfos[NUMPEDINFONODES] = {
{ nil, PED_FOOTR, PEDPIECE_RIGHTLEG, 0.0f, 0.15f, 0.15f }, { nil, PED_FOOTR, PEDPIECE_RIGHTLEG, 0.0f, 0.15f, 0.15f },
}; };
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 == PEDPIECE_HEAD)
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, SURFACE_FLESH, 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);
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);
colmodel->level = LEVEL_NONE;
m_hitColModel = colmodel;
}
CColModel*
CPedModelInfo::AnimatePedColModel(CColModel* colmodel, RwFrame* frame)
{
RwObjectNameAssociation nameAssoc;
RwObjectIdAssociation idAssoc;
RwMatrix* mat = RwMatrixCreate();
CColSphere* spheres = colmodel->spheres;
for (int i = 0; i < NUMPEDINFONODES; i++) {
RwFrame* f = nil;
if (m_pColNodeInfos[i].name) {
nameAssoc.name = m_pColNodeInfos[i].name;
nameAssoc.frame = nil;
RwFrameForAllChildren(frame, FindFrameFromNameCB, &nameAssoc);
f = nameAssoc.frame;
}
else {
idAssoc.id = m_pColNodeInfos[i].pedNode;
idAssoc.frame = nil;
RwFrameForAllChildren(frame, FindFrameFromIdCB, &idAssoc);
f = idAssoc.frame;
}
if (f) {
RwMatrixCopy(mat, RwFrameGetMatrix(f));
for (f = RwFrameGetParent(f); f; f = RwFrameGetParent(f)) {
RwMatrixTransform(mat, RwFrameGetMatrix(f), rwCOMBINEPOSTCONCAT);
if (RwFrameGetParent(f) == frame)
break;
}
spheres[i].center.x = mat->pos.x + m_pColNodeInfos[i].x;
spheres[i].center.y = mat->pos.y + 0.0f;
spheres[i].center.z = mat->pos.z + m_pColNodeInfos[i].z;
}
}
return colmodel;
}
#ifdef PED_SKIN
void void
CPedModelInfo::CreateHitColModelSkinned(RpClump *clump) CPedModelInfo::CreateHitColModelSkinned(RpClump *clump)
{ {
@ -384,4 +146,26 @@ CPedModelInfo::AnimatePedColModelSkinned(RpClump *clump)
return m_hitColModel; return m_hitColModel;
} }
#endif CColModel*
CPedModelInfo::AnimatePedColModelSkinnedWorld(RpClump *clump)
{
if(m_hitColModel == nil)
CreateHitColModelSkinned(clump);
CColSphere *spheres = m_hitColModel->spheres;
RpHAnimHierarchy *hier = GetAnimHierarchyFromSkinClump(clump);
RwMatrix *mat;
for(int i = 0; i < NUMPEDINFONODES; i++){
int id = ConvertPedNode2BoneTag(m_pColNodeInfos[i].pedNode);
int idx = RpHAnimIDGetIndex(hier, id);
mat = &RpHAnimHierarchyGetMatrixArray(hier)[idx];
RwV3d pos = { 0.0f, 0.0f, 0.0f };
RwV3dTransformPoints(&pos, &pos, 1, mat);
spheres[i].center.x = pos.x + m_pColNodeInfos[i].x;
spheres[i].center.y = pos.y + 0.0f;
spheres[i].center.z = pos.z + m_pColNodeInfos[i].z;
}
return m_hitColModel;
}

View file

@ -36,32 +36,17 @@ public:
ePedStats m_pedStatType; ePedStats m_pedStatType;
uint32 m_carsCanDrive; uint32 m_carsCanDrive;
CColModel *m_hitColModel; CColModel *m_hitColModel;
#ifdef PED_SKIN int8 radio1, radio2;
RpAtomic *m_head;
RpAtomic *m_lhand;
RpAtomic *m_rhand;
#endif
static RwObjectNameIdAssocation m_pPedIds[PED_NODE_MAX]; static RwObjectNameIdAssocation m_pPedIds[PED_NODE_MAX];
CPedModelInfo(void) : CClumpModelInfo(MITYPE_PED) { } CPedModelInfo(void) : CClumpModelInfo(MITYPE_PED) { m_hitColModel = nil; }
~CPedModelInfo(void) { delete m_hitColModel; }
void DeleteRwObject(void); void DeleteRwObject(void);
void SetClump(RpClump *); void SetClump(RpClump *);
void SetLowDetailClump(RpClump*);
void CreateHitColModel(void);
void CreateHitColModelSkinned(RpClump *clump); void CreateHitColModelSkinned(RpClump *clump);
CColModel *GetHitColModel(void) { return m_hitColModel; } CColModel *GetHitColModel(void) { return m_hitColModel; }
static CColModel *AnimatePedColModel(CColModel* colmodel, RwFrame* frame);
CColModel *AnimatePedColModelSkinned(RpClump *clump); CColModel *AnimatePedColModelSkinned(RpClump *clump);
CColModel *AnimatePedColModelSkinnedWorld(RpClump *clump);
#ifdef PED_SKIN
static RpAtomic *findLimbsCb(RpAtomic *atomic, void *data);
RpAtomic *getHead(void) { return m_head; }
RpAtomic *getLeftHand(void) { return m_lhand; }
RpAtomic *getRightHand(void) { return m_rhand; }
#endif
}; };
#ifndef PED_SKIN
static_assert(sizeof(CPedModelInfo) == 0x48, "CPedModelInfo: error");
#endif

View file

@ -5153,12 +5153,9 @@ CPed::FightStrike(CVector &touchedNodePos)
// He can beat us // He can beat us
if (sq(maxDistanceToBeBeaten) > potentialAttackDistance.MagnitudeSqr()) { if (sq(maxDistanceToBeBeaten) > potentialAttackDistance.MagnitudeSqr()) {
#ifdef PED_SKIN
// Have to animate a skinned clump because the initial col model is useless // Have to animate a skinned clump because the initial col model is useless
if(IsClumpSkinned(GetClump())) ourCol = ((CPedModelInfo *)CModelInfo::GetModelInfo(GetModelIndex()))->AnimatePedColModelSkinned(GetClump());
ourCol = ((CPedModelInfo *)CModelInfo::GetModelInfo(GetModelIndex()))->AnimatePedColModelSkinned(GetClump()); /* this should all be gone, right?
else
#endif
if (nearPed->m_nPedState == PED_FALL if (nearPed->m_nPedState == PED_FALL
|| nearPed->m_nPedState == PED_DEAD || nearPed->m_nPedState == PED_DIE || nearPed->m_nPedState == PED_DEAD || nearPed->m_nPedState == PED_DIE
|| !nearPed->IsPedHeadAbovePos(-0.3f)) { || !nearPed->IsPedHeadAbovePos(-0.3f)) {
@ -5171,6 +5168,7 @@ CPed::FightStrike(CVector &touchedNodePos)
ourCol = ((CPedModelInfo*)CModelInfo::GetModelInfo(m_modelIndex))->GetHitColModel(); ourCol = ((CPedModelInfo*)CModelInfo::GetModelInfo(m_modelIndex))->GetHitColModel();
#endif #endif
} }
*/
for (int j = 0; j < ourCol->numSpheres; j++) { for (int j = 0; j < ourCol->numSpheres; j++) {
attackDistance = nearPed->GetPosition() + ourCol->spheres[j].center; attackDistance = nearPed->GetPosition() + ourCol->spheres[j].center;
@ -12606,13 +12604,7 @@ CPed::Render(void)
bRenderPedInCar && sq(25.0f * TheCamera.LODDistMultiplier) >= (TheCamera.GetPosition() - GetPosition()).MagnitudeSqr()) { bRenderPedInCar && sq(25.0f * TheCamera.LODDistMultiplier) >= (TheCamera.GetPosition() - GetPosition()).MagnitudeSqr()) {
CEntity::Render(); CEntity::Render();
#ifdef PED_SKIN if(m_pWeaponModel){
if(IsClumpSkinned(GetClump())){
renderLimb(PED_HEAD);
renderLimb(PED_HANDL);
renderLimb(PED_HANDR);
}
if(m_pWeaponModel && IsClumpSkinned(GetClump())){
RpHAnimHierarchy *hier = GetAnimHierarchyFromSkinClump(GetClump()); RpHAnimHierarchy *hier = GetAnimHierarchyFromSkinClump(GetClump());
int idx = RpHAnimIDGetIndex(hier, m_pFrames[PED_HANDR]->nodeID); int idx = RpHAnimIDGetIndex(hier, m_pFrames[PED_HANDR]->nodeID);
RwMatrix *mat = &RpHAnimHierarchyGetMatrixArray(hier)[idx]; RwMatrix *mat = &RpHAnimHierarchyGetMatrixArray(hier)[idx];
@ -12621,51 +12613,9 @@ CPed::Render(void)
RwFrameUpdateObjects(frame); RwFrameUpdateObjects(frame);
RpAtomicRender(m_pWeaponModel); RpAtomicRender(m_pWeaponModel);
} }
#endif
} }
} }
#ifdef PED_SKIN
static RpMaterial*
SetLimbAlphaCB(RpMaterial *material, void *data)
{
((RwRGBA*)RpMaterialGetColor(material))->alpha = *(uint8*)data;
return material;
}
void
CPed::renderLimb(int node)
{
RpHAnimHierarchy *hier = GetAnimHierarchyFromSkinClump(GetClump());
int idx = RpHAnimIDGetIndex(hier, m_pFrames[node]->nodeID);
RwMatrix *mat = &RpHAnimHierarchyGetMatrixArray(hier)[idx];
CPedModelInfo *mi = (CPedModelInfo *)CModelInfo::GetModelInfo(GetModelIndex());
RpAtomic *atomic;
switch(node){
case PED_HEAD:
atomic = mi->getHead();
break;
case PED_HANDL:
atomic = mi->getLeftHand();
break;
case PED_HANDR:
atomic = mi->getRightHand();
break;
default:
return;
}
if(atomic == nil)
return;
RwFrame *frame = RpAtomicGetFrame(atomic);
*RwFrameGetMatrix(frame) = *mat;
RwFrameUpdateObjects(frame);
int alpha = CVisibilityPlugins::GetClumpAlpha(GetClump());
RpGeometryForAllMaterials(RpAtomicGetGeometry(atomic), SetLimbAlphaCB, &alpha);
RpAtomicRender(atomic);
}
#endif
void void
CPed::ProcessObjective(void) CPed::ProcessObjective(void)
{ {

View file

@ -890,10 +890,6 @@ public:
void DebugRenderOnePedText(void); void DebugRenderOnePedText(void);
#endif #endif
#ifdef PED_SKIN
void renderLimb(int node);
#endif
#ifdef COMPATIBLE_SAVES #ifdef COMPATIBLE_SAVES
virtual void Save(uint8*& buf); virtual void Save(uint8*& buf);
virtual void Load(uint8*& buf); virtual void Load(uint8*& buf);