Skip to content
Merged
Show file tree
Hide file tree
Changes from 38 commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
7b327e9
Allow change model flags
TheNormalnij Oct 14, 2020
89c1ef4
Fix typo
TheNormalnij Oct 26, 2020
3692da2
Fix typo
TheNormalnij Oct 26, 2020
1d8aea3
Fix engineResetModelFlags
TheNormalnij Oct 27, 2020
adef19c
Removed model name interface
TheNormalnij Oct 27, 2020
164321f
Merge remote-tracking branch 'origin/model_flags' into model_flags
TheNormalnij Oct 27, 2020
9747ac3
Changed interface
TheNormalnij Oct 27, 2020
454c562
Fix GetOriginalFlags
TheNormalnij Oct 27, 2020
77a5ec2
Fix optional argument
TheNormalnij Oct 27, 2020
f62aa61
Merge branch 'master' into model_flags
TheNormalnij Oct 28, 2020
5701245
Used new parser
TheNormalnij Oct 28, 2020
29040a5
Merge branch 'master' into model_flags
TheNormalnij Oct 30, 2020
0d6fca2
Fix build
TheNormalnij Oct 30, 2020
46d778d
Little defs refactor
TheNormalnij Nov 3, 2020
3f43221
Merge branch 'master' into model_flags
TheNormalnij Nov 3, 2020
9d0f75b
Reversed GTA SA flags interface
TheNormalnij Nov 5, 2020
ba36bd0
Added enums for model flags
TheNormalnij Nov 9, 2020
0918bdb
Fix build
TheNormalnij Nov 9, 2020
65ac371
Changed flag name
TheNormalnij Nov 9, 2020
bd11919
Don't allow change bIsColLoaded flag
TheNormalnij Nov 10, 2020
92709f3
Added EngineGetModelFlag and EngineSetModelFlag functions
TheNormalnij Nov 10, 2020
124b940
Merge remote-tracking branch 'upstream/master' into model_flags
TheNormalnij Nov 11, 2020
af02481
Fix API
TheNormalnij Nov 11, 2020
609feca
Fix missing "is_crane"
TheNormalnij Nov 11, 2020
fee73e8
Removed old unused code
TheNormalnij Nov 12, 2020
fdd6cdb
Fix grammar
TheNormalnij Nov 12, 2020
2e10c6a
Removed useless defs
TheNormalnij Nov 12, 2020
cbfe499
Little fix
TheNormalnij Nov 12, 2020
49abec6
Update Client/sdk/game/CModelInfo.h
TheNormalnij Nov 12, 2020
710b65e
Some fixes
TheNormalnij Nov 12, 2020
224d7ff
Merge branch 'master' into model_flags
Apr 12, 2021
5204e01
resolve conversions
Apr 12, 2021
e511868
Merge remote-tracking branch 'mta_home/master' into model_flags
Sep 25, 2021
114e030
Fix build
Sep 25, 2021
5d2fa30
Fix logical conflict
Sep 25, 2021
646285f
Merge branch 'master' into model_flags
patrikjuvonen Jan 1, 2023
ec5bb3f
Addendum to previous merge commit
patrikjuvonen Jan 1, 2023
dfd75ea
Merge branch 'master' into model_flags
patrikjuvonen Jan 1, 2023
949f1ce
Merge branch 'master' into model_flags
patrikjuvonen Apr 7, 2023
80558c2
Fix merge conflict
patrikjuvonen Apr 7, 2023
8057836
Merge branch 'master' into model_flags
patrikjuvonen Apr 7, 2023
b007054
Update CMultiplayerSA_CrashFixHacks.cpp
patrikjuvonen Apr 7, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions Client/game_sa/CGameSA.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -882,6 +882,11 @@ void CGameSA::ResetModelLodDistances()
CModelInfoSA::StaticResetLodDistances();
}

void CGameSA::ResetModelFlags()
{
CModelInfoSA::StaticResetFlags();
}

void CGameSA::ResetModelTimes()
{
CModelInfoSA::StaticResetModelTimes();
Expand Down
1 change: 1 addition & 0 deletions Client/game_sa/CGameSA.h
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,7 @@ class CGameSA : public CGame
CWeaponStat* CreateWeaponStat(eWeaponType weaponType, eWeaponSkill weaponSkill);
void FlushPendingRestreamIPL();
void ResetModelLodDistances();
void ResetModelFlags();
void ResetAlphaTransparencies();
void DisableVSync();
void ResetModelTimes();
Expand Down
288 changes: 275 additions & 13 deletions Client/game_sa/CModelInfoSA.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,49 @@ CBaseModelInfoSAInterface** ppModelInfo = (CBaseModelInfoSAInterface**)ARRAY_Mod

std::map<unsigned short, int> CModelInfoSA::ms_RestreamTxdIDMap;
std::map<DWORD, float> CModelInfoSA::ms_ModelDefaultLodDistanceMap;
std::map<DWORD, unsigned short> CModelInfoSA::ms_ModelDefaultFlagsMap;
std::map<DWORD, BYTE> CModelInfoSA::ms_ModelDefaultAlphaTransparencyMap;
std::unordered_map<std::uint32_t, std::map<eVehicleDummies, CVector>> CModelInfoSA::ms_ModelDefaultDummiesPosition;
std::map<CTimeInfoSAInterface*, CTimeInfoSAInterface*> CModelInfoSA::ms_ModelDefaultModelTimeInfo;
std::unordered_map<DWORD, unsigned short> CModelInfoSA::ms_OriginalObjectPropertiesGroups;
std::unordered_map<DWORD, std::pair<float, float>> CModelInfoSA::ms_VehicleModelDefaultWheelSizes;

union tIdeFlags
{
struct
{
char bIsRoad : 1;
char bFlag2 : 1;
char bDrawLast : 1;
char bAdditive : 1;
char bFlag5 : 1;
char bFlag6 : 1;
char bNoZBufferWrite : 1;
char bDontReceiveShadows : 1;

char bFlag9 : 1;
char bIsGlassType1 : 1;
char bIsGlassType2 : 1;
char bIsGarageDoor : 1;
char bIsDamagable : 1;
char bIsTree : 1;
char bIsPalm : 1;
char bDontCollideWithFlyer : 1;

char bFlag17 : 1;
char bFlag18 : 1;
char bFlag19 : 1;
char bFlag20 : 1;
char bIsTag : 1;
char bDisableBackfaceCulling : 1;
char bIsBreakableStatue : 1;
char bFlag24 : 1;

char cPad : 8;
};
unsigned int uiFlags;
};

static constexpr uintptr_t vftable_CVehicleModelInfo = 0x85C5C8u;
static constexpr size_t RESOURCE_ID_COL = 25000;

Expand Down Expand Up @@ -459,19 +496,245 @@ bool CModelInfoSA::DoIsLoaded()
return bLoaded;
}

BYTE CModelInfoSA::GetFlags()
unsigned short CModelInfoSA::GetFlags()
{
DWORD dwFunc = FUNC_GetModelFlags;
DWORD ModelID = m_dwModelID;
BYTE bFlags = 0;
_asm
return ppModelInfo[m_dwModelID]->usFlags;
}

unsigned short CModelInfoSA::GetOriginalFlags()
{
if (MapContains(ms_ModelDefaultFlagsMap, m_dwModelID))
return MapGet(ms_ModelDefaultFlagsMap, m_dwModelID);

return ppModelInfo[m_dwModelID]->usFlags;
}

void CModelInfoSA::SetFlags(unsigned short usFlags)
{
m_pInterface = ppModelInfo[m_dwModelID];
if (!m_pInterface)
return;

// Save default value if not done yet
if (!MapContains(ms_ModelDefaultFlagsMap, m_dwModelID))
MapSet(ms_ModelDefaultFlagsMap, m_dwModelID, m_pInterface->usFlags);

// Don't change bIsColLoaded flag
usFlags &= 0xFF7F; // Disable flag in input
usFlags |= m_pInterface->usFlags & 0x80; // Apply current bIsColLoaded flag

m_pInterface->usFlags = usFlags;
}

void CModelInfoSA::SetIdeFlags(unsigned int uiFlags)
{
m_pInterface = ppModelInfo[m_dwModelID];
if (!m_pInterface)
return;

// Save default value if not done yet
if (!MapContains(ms_ModelDefaultFlagsMap, m_dwModelID))
MapSet(ms_ModelDefaultFlagsMap, m_dwModelID, m_pInterface->usFlags);

tIdeFlags ideFlags;
ideFlags.uiFlags = uiFlags;

// Default value is 0xC0 (bIsColLoaded + bIsBackfaceCulled)
// But bIsColLoaded should not be changed
m_pInterface->usFlags &= 0x80; // Reset all flags except bIsColLoaded
m_pInterface->bIsBackfaceCulled = true;

// setBaseModelInfoFlags
if (ideFlags.bDrawLast)
{
push ModelID
call dwFunc
add esp, 4
mov bFlags, al
m_pInterface->bAlphaTransparency = true;
m_pInterface->bAdditiveRender = true;
}

m_pInterface->bAdditiveRender = ideFlags.bAdditive;
m_pInterface->bDontWriteZBuffer = ideFlags.bNoZBufferWrite;
m_pInterface->bDontCastShadowsOn = ideFlags.bDontReceiveShadows;
m_pInterface->bIsBackfaceCulled = !ideFlags.bDisableBackfaceCulling;

switch (GetModelType())
{
case eModelInfoType::ATOMIC:
case eModelInfoType::TIME:
{
// SetAtomicModelInfoFlags
m_pInterface->bIsRoad = ideFlags.bIsRoad;

m_pInterface->bDontCollideWithFlyer = ideFlags.bDontCollideWithFlyer;

if (ideFlags.bFlag20)
m_pInterface->eSpecialModelType = eModelSpecialType::CRANE;
else if (ideFlags.bFlag24)
m_pInterface->eSpecialModelType = eModelSpecialType::UNKNOW_1;
else if (ideFlags.bIsBreakableStatue)
m_pInterface->eSpecialModelType = eModelSpecialType::BREAKABLE_STATUE;
else if (ideFlags.bIsTag)
m_pInterface->eSpecialModelType = eModelSpecialType::TAG;
else if (ideFlags.bIsPalm)
m_pInterface->eSpecialModelType = eModelSpecialType::PALM;
else if (ideFlags.bIsTree)
m_pInterface->eSpecialModelType = eModelSpecialType::TREE;
else if (ideFlags.bIsGarageDoor)
m_pInterface->eSpecialModelType = eModelSpecialType::GARAGE_DOOR;
else if (ideFlags.bIsGlassType2)
m_pInterface->eSpecialModelType = eModelSpecialType::GLASS_2;
else if (ideFlags.bIsGlassType1)
m_pInterface->eSpecialModelType = eModelSpecialType::GLASS_1;
break;
}
case eModelInfoType::CLUMP:
{
m_pInterface->bAdditiveRender = ideFlags.bFlag6;
break;
}
default:
break;
}

}

void CModelInfoSA::SetIdeFlag(eModelIdeFlag eIdeFlag, bool bState)
{
m_pInterface = ppModelInfo[m_dwModelID];
if (!m_pInterface)
return;

switch (eIdeFlag)
{
case eModelIdeFlag::IS_ROAD:
m_pInterface->bIsRoad = bState;
break;
case eModelIdeFlag::DRAW_LAST:
m_pInterface->bAlphaTransparency = bState;
if (bState)
m_pInterface->bAdditiveRender = true;
break;
case eModelIdeFlag::ADDITIVE:
m_pInterface->bAdditiveRender = bState;
break;
case eModelIdeFlag::IGNORE_LIGHTING:
m_pInterface->bAdditiveRender = bState;
break;
case eModelIdeFlag::NO_ZBUFFER_WRITE:
m_pInterface->bDontWriteZBuffer = bState;
break;
case eModelIdeFlag::DONT_RECEIVE_SHADOWS:
m_pInterface->bDontCastShadowsOn = bState;
break;
case eModelIdeFlag::IS_GLASS_TYPE_1:
SetModelSpecialType(eModelSpecialType::GLASS_1, bState);
break;
case eModelIdeFlag::IS_GLASS_TYPE_2:
SetModelSpecialType(eModelSpecialType::GLASS_2, bState);
break;
case eModelIdeFlag::IS_GARAGE_DOOR:
SetModelSpecialType(eModelSpecialType::GARAGE_DOOR, bState);
break;
case eModelIdeFlag::IS_TREE:
SetModelSpecialType(eModelSpecialType::TREE, bState);
break;
case eModelIdeFlag::IS_PALM:
SetModelSpecialType(eModelSpecialType::PALM, bState);
break;
case eModelIdeFlag::IS_TAG:
SetModelSpecialType(eModelSpecialType::TAG, bState);
break;
case eModelIdeFlag::IS_BREAKABLE_STATUE:
SetModelSpecialType(eModelSpecialType::BREAKABLE_STATUE, bState);
break;
case eModelIdeFlag::IS_CRANE:
SetModelSpecialType(eModelSpecialType::CRANE, bState);
break;
case eModelIdeFlag::IS_DAMAGABLE:
// Can't set
break;
case eModelIdeFlag::DOES_NOT_COLLIDE_WITH_FLYER:
m_pInterface->bDontCollideWithFlyer = bState;
break;
case eModelIdeFlag::DISABLE_BACKFACE_CULLING:
m_pInterface->bIsBackfaceCulled = !bState;
break;
default:
break;
}
}

bool CModelInfoSA::GetIdeFlag(eModelIdeFlag eIdeFlag)
{
m_pInterface = ppModelInfo[m_dwModelID];
if (!m_pInterface)
return false;

switch (eIdeFlag)
{
case eModelIdeFlag::IS_ROAD:
return m_pInterface->bIsRoad;
case eModelIdeFlag::DRAW_LAST:
return m_pInterface->bAlphaTransparency;
case eModelIdeFlag::ADDITIVE:
return m_pInterface->bAdditiveRender;
case eModelIdeFlag::IGNORE_LIGHTING:
return m_pInterface->bAdditiveRender;
case eModelIdeFlag::NO_ZBUFFER_WRITE:
return m_pInterface->bDontWriteZBuffer;
case eModelIdeFlag::DONT_RECEIVE_SHADOWS:
return m_pInterface->bDontCastShadowsOn;
case eModelIdeFlag::IS_GLASS_TYPE_1:
return m_pInterface->eSpecialModelType == eModelSpecialType::GLASS_1;
case eModelIdeFlag::IS_GLASS_TYPE_2:
return m_pInterface->eSpecialModelType == eModelSpecialType::GLASS_2;
case eModelIdeFlag::IS_GARAGE_DOOR:
return m_pInterface->eSpecialModelType == eModelSpecialType::GARAGE_DOOR;
case eModelIdeFlag::IS_TREE:
return m_pInterface->eSpecialModelType == eModelSpecialType::TREE;
case eModelIdeFlag::IS_PALM:
return m_pInterface->eSpecialModelType == eModelSpecialType::PALM;
case eModelIdeFlag::IS_TAG:
return m_pInterface->eSpecialModelType == eModelSpecialType::TAG;
case eModelIdeFlag::IS_BREAKABLE_STATUE:
return m_pInterface->eSpecialModelType == eModelSpecialType::BREAKABLE_STATUE;
case eModelIdeFlag::IS_CRANE:
return m_pInterface->eSpecialModelType == eModelSpecialType::CRANE;
case eModelIdeFlag::IS_DAMAGABLE:
return ((bool (*)())m_pInterface->VFTBL->AsDamageAtomicModelInfoPtr)();
case eModelIdeFlag::DOES_NOT_COLLIDE_WITH_FLYER:
return m_pInterface->bDontCollideWithFlyer;
case eModelIdeFlag::DISABLE_BACKFACE_CULLING:
return !m_pInterface->bIsBackfaceCulled;
default:
return false;
}
}

void CModelInfoSA::SetModelSpecialType(eModelSpecialType eType, bool bState)
{
if (bState)
m_pInterface->eSpecialModelType = eType;
else if (m_pInterface->eSpecialModelType == eType)
m_pInterface->eSpecialModelType = eModelSpecialType::NONE;
}

void CModelInfoSA::StaticResetFlags()
{
// Restore default values
for (std::map<DWORD, unsigned short>::const_iterator iter = ms_ModelDefaultFlagsMap.begin(); iter != ms_ModelDefaultFlagsMap.end(); ++iter)
{
CBaseModelInfoSAInterface* pInterface = ppModelInfo[iter->first];
if (pInterface)
{
// Don't change bIsColLoaded flag
ushort usFlags = iter->second;
usFlags &= 0xFF7F;
usFlags |= pInterface->usFlags & 0x80;
pInterface->usFlags = usFlags;
}
}
return bFlags;

ms_ModelDefaultFlagsMap.clear();
}

CBoundingBox* CModelInfoSA::GetBoundingBox()
Expand Down Expand Up @@ -1274,7 +1537,7 @@ void CModelInfoSA::SetColModel(CColModel* pColModel)
if (!m_pOriginalColModelInterface)
{
m_pOriginalColModelInterface = m_pInterface->pColModel;
m_originalFlags = m_pInterface->flags;
m_originalFlags = GetOriginalFlags();
}

// Apply some low-level hacks
Expand All @@ -1285,7 +1548,6 @@ void CModelInfoSA::SetColModel(CColModel* pColModel)

// SetColModel sets bDoWeOwnTheColModel if the last parameter is truthy
m_pInterface->bDoWeOwnTheColModel = false;
m_pInterface->bCollisionWasStreamedWithModel = false;

// Set some lighting for this collision if not already present
CColDataSA* pColData = pColModelInterface->m_data;
Expand Down Expand Up @@ -1316,7 +1578,7 @@ void CModelInfoSA::RestoreColModel()
CBaseModelInfo_SetColModel(m_pInterface, m_pOriginalColModelInterface, true);
CColAccel_addCacheCol(m_dwModelID, m_pInterface->pColModel);

m_pInterface->flags = m_originalFlags;
m_pInterface->usFlags = m_originalFlags;

// Force the game to load the original collision model data, if we applied a custom collision model before
// there was any object/building, which would've provoked CColStore to request it.
Expand Down
Loading