[Zones] Added support for FF version 448, 460, 461
This commit is contained in:
parent
138d6ad1dd
commit
530d773d49
@ -112,5 +112,9 @@ namespace Components
|
|||||||
Utils::Hook::Set<BYTE>(0x4A95F8, 32);
|
Utils::Hook::Set<BYTE>(0x4A95F8, 32);
|
||||||
|
|
||||||
Utils::Hook::Set<int>(0x42F22B, offsetof(Game::newMapArena_t, mapName) - offsetof(Game::newMapArena_t, other));
|
Utils::Hook::Set<int>(0x42F22B, offsetof(Game::newMapArena_t, mapName) - offsetof(Game::newMapArena_t, other));
|
||||||
|
|
||||||
|
// patch max arena count
|
||||||
|
constexpr auto arenaCount = sizeof(ArenaLength::NewArenas) / sizeof(Game::newMapArena_t);
|
||||||
|
Utils::Hook::Set<std::uint32_t>(0x630AA3, arenaCount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -216,7 +216,7 @@ namespace Components
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Fix shader const stuff
|
// Fix shader const stuff
|
||||||
if (type == Game::XAssetType::ASSET_TYPE_TECHNIQUE_SET && Zones::Version() >= 359)
|
if (type == Game::XAssetType::ASSET_TYPE_TECHNIQUE_SET && Zones::Version() >= 359 && Zones::Version() < 448)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < 48; ++i)
|
for (int i = 0; i < 48; ++i)
|
||||||
{
|
{
|
||||||
@ -533,6 +533,210 @@ namespace Components
|
|||||||
|
|
||||||
AssetHandler::OnLoad([](Game::XAssetType type, Game::XAssetHeader asset, std::string name, bool*)
|
AssetHandler::OnLoad([](Game::XAssetType type, Game::XAssetHeader asset, std::string name, bool*)
|
||||||
{
|
{
|
||||||
|
#ifdef DEBUG
|
||||||
|
// #define DUMP_TECHSETS
|
||||||
|
#ifdef DUMP_TECHSETS
|
||||||
|
if (type == Game::XAssetType::ASSET_TYPE_VERTEXDECL && !name.empty() && name[0] != ',')
|
||||||
|
{
|
||||||
|
std::filesystem::create_directories("techsets/vertexdecl");
|
||||||
|
|
||||||
|
auto vertexdecl = asset.vertexDecl;
|
||||||
|
|
||||||
|
std::vector<json11::Json> routingData;
|
||||||
|
for (int i = 0; i < vertexdecl->streamCount; i++)
|
||||||
|
{
|
||||||
|
routingData.push_back(json11::Json::object
|
||||||
|
{
|
||||||
|
{ "source", (int)vertexdecl->routing.data[i].source },
|
||||||
|
{ "dest", (int)vertexdecl->routing.data[i].dest },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<json11::Json> declData;
|
||||||
|
for (int i = 0; i < 16; i++)
|
||||||
|
{
|
||||||
|
if (vertexdecl->routing.decl[i])
|
||||||
|
{
|
||||||
|
routingData.push_back(int(vertexdecl->routing.decl[i]));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
routingData.push_back(nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
json11::Json vertexData = json11::Json::object
|
||||||
|
{
|
||||||
|
{ "name", vertexdecl->name },
|
||||||
|
{ "streamCount", vertexdecl->streamCount },
|
||||||
|
{ "hasOptionalSource", vertexdecl->hasOptionalSource },
|
||||||
|
{ "routing", routingData },
|
||||||
|
{ "decl", declData },
|
||||||
|
};
|
||||||
|
|
||||||
|
auto stringData = vertexData.dump();
|
||||||
|
|
||||||
|
auto fp = fopen(Utils::String::VA("techsets/vertexdecl/%s.%s.json", vertexdecl->name, Zones::Version() > 276 ? "codo" : "iw4"), "wb");
|
||||||
|
fwrite(&stringData[0], stringData.size(), 1, fp);
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == Game::ASSET_TYPE_TECHNIQUE_SET && !name.empty() && name[0] != ',')
|
||||||
|
{
|
||||||
|
std::filesystem::create_directory("techsets");
|
||||||
|
std::filesystem::create_directories("techsets/techniques");
|
||||||
|
|
||||||
|
auto techset = asset.techniqueSet;
|
||||||
|
|
||||||
|
std::vector<json11::Json> techniques;
|
||||||
|
for (int technique = 0; technique < 48; technique++)
|
||||||
|
{
|
||||||
|
auto curTech = techset->techniques[technique];
|
||||||
|
if (curTech)
|
||||||
|
{
|
||||||
|
std::vector<json11::Json> passDataArray;
|
||||||
|
for (int pass = 0; pass < curTech->passCount; pass++)
|
||||||
|
{
|
||||||
|
auto curPass = &curTech->passArray[pass];
|
||||||
|
|
||||||
|
std::vector<json11::Json> argDataArray;
|
||||||
|
for (int arg = 0; arg < curPass->perObjArgCount + curPass->perPrimArgCount + curPass->stableArgCount; arg++)
|
||||||
|
{
|
||||||
|
auto curArg = &curPass->args[arg];
|
||||||
|
|
||||||
|
if (curArg->type == 1 || curArg->type == 7)
|
||||||
|
{
|
||||||
|
std::vector<float> literalConsts;
|
||||||
|
if (curArg->u.literalConst != 0)
|
||||||
|
{
|
||||||
|
literalConsts.push_back(curArg->u.literalConst[0]);
|
||||||
|
literalConsts.push_back(curArg->u.literalConst[1]);
|
||||||
|
literalConsts.push_back(curArg->u.literalConst[2]);
|
||||||
|
literalConsts.push_back(curArg->u.literalConst[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
json11::Json argData = json11::Json::object
|
||||||
|
{
|
||||||
|
{ "type", curArg->type },
|
||||||
|
{ "value", literalConsts },
|
||||||
|
};
|
||||||
|
argDataArray.push_back(argData);
|
||||||
|
}
|
||||||
|
else if (curArg->type == 3 || curArg->type == 5)
|
||||||
|
{
|
||||||
|
json11::Json argData = json11::Json::object
|
||||||
|
{
|
||||||
|
{ "type", curArg->type },
|
||||||
|
{ "firstRow", curArg->u.codeConst.firstRow },
|
||||||
|
{ "rowCount", curArg->u.codeConst.rowCount },
|
||||||
|
{ "index", curArg->u.codeConst.index },
|
||||||
|
};
|
||||||
|
argDataArray.push_back(argData);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
json11::Json argData = json11::Json::object
|
||||||
|
{
|
||||||
|
{ "type", curArg->type },
|
||||||
|
{ "value", static_cast<int>(curArg->u.codeSampler) },
|
||||||
|
};
|
||||||
|
argDataArray.push_back(argData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
json11::Json passData = json11::Json::object
|
||||||
|
{
|
||||||
|
{ "perObjArgCount", curPass->perObjArgCount },
|
||||||
|
{ "perPrimArgCount", curPass->perPrimArgCount },
|
||||||
|
{ "stableArgCount", curPass->stableArgCount },
|
||||||
|
{ "args", argDataArray },
|
||||||
|
{ "pixelShader", curPass->pixelShader ? curPass->pixelShader->name : "" },
|
||||||
|
{ "vertexShader", curPass->vertexShader ? curPass->vertexShader->name : "" },
|
||||||
|
{ "vertexDecl", curPass->vertexDecl ? curPass->vertexDecl->name : "" },
|
||||||
|
};
|
||||||
|
passDataArray.push_back(passData);
|
||||||
|
}
|
||||||
|
|
||||||
|
json11::Json techData = json11::Json::object
|
||||||
|
{
|
||||||
|
{ "name", curTech->name },
|
||||||
|
{ "index", technique },
|
||||||
|
{ "flags", curTech->flags },
|
||||||
|
{ "numPasses", curTech->passCount },
|
||||||
|
{ "pass", passDataArray },
|
||||||
|
};
|
||||||
|
|
||||||
|
auto stringData = techData.dump();
|
||||||
|
|
||||||
|
auto fp = fopen(Utils::String::VA("techsets/techniques/%s.%s.json", curTech->name, Zones::Version() > 276 ? "codo" : "iw4"), "wb");
|
||||||
|
fwrite(&stringData[0], stringData.size(), 1, fp);
|
||||||
|
fclose(fp);
|
||||||
|
|
||||||
|
json11::Json techsetTechnique = json11::Json::object
|
||||||
|
{
|
||||||
|
{ "name", curTech->name },
|
||||||
|
{ "index", technique },
|
||||||
|
};
|
||||||
|
techniques.push_back(techsetTechnique);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
techniques.push_back(nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
json11::Json techsetData = json11::Json::object
|
||||||
|
{
|
||||||
|
{ "name", techset->name },
|
||||||
|
{ "techniques", techniques },
|
||||||
|
};
|
||||||
|
|
||||||
|
auto stringData = techsetData.dump();
|
||||||
|
|
||||||
|
auto fp = fopen(Utils::String::VA("techsets/%s.%s.json", techset->name, Zones::Version() > 276 ? "codo" : "iw4"), "wb");
|
||||||
|
fwrite(&stringData[0], stringData.size(), 1, fp);
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (type == Game::XAssetType::ASSET_TYPE_TECHNIQUE_SET && Zones::Version() >= 460)
|
||||||
|
{
|
||||||
|
auto techset = asset.techniqueSet;
|
||||||
|
if (techset)
|
||||||
|
{
|
||||||
|
for (int t = 0; t < 48; t++)
|
||||||
|
{
|
||||||
|
if (techset->techniques[t])
|
||||||
|
{
|
||||||
|
for (int p = 0; p < techset->techniques[t]->passCount; p++)
|
||||||
|
{
|
||||||
|
for (int a = 0; a < techset->techniques[t]->passArray[p].perObjArgCount +
|
||||||
|
techset->techniques[t]->passArray[p].perPrimArgCount +
|
||||||
|
techset->techniques[t]->passArray[p].stableArgCount; a++)
|
||||||
|
{
|
||||||
|
auto arg = &techset->techniques[t]->passArray[p].args[a];
|
||||||
|
if (arg->type == 3 || arg->type == 5)
|
||||||
|
{
|
||||||
|
if (arg->u.codeConst.index > 140)
|
||||||
|
{
|
||||||
|
OutputDebugStringA(Utils::String::VA("codeConst %i is out of range for %s::%s[%i]\n", arg->u.codeConst.index,
|
||||||
|
techset->name, techset->techniques[t]->name, p));
|
||||||
|
|
||||||
|
if (!ZoneBuilder::IsEnabled())
|
||||||
|
{
|
||||||
|
__debugbreak();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
if (Dvar::Var("r_noVoid").get<bool>() && type == Game::XAssetType::ASSET_TYPE_XMODEL && name == "void")
|
if (Dvar::Var("r_noVoid").get<bool>() && type == Game::XAssetType::ASSET_TYPE_XMODEL && name == "void")
|
||||||
{
|
{
|
||||||
asset.model->numLods = 0;
|
asset.model->numLods = 0;
|
||||||
@ -540,16 +744,16 @@ namespace Components
|
|||||||
});
|
});
|
||||||
|
|
||||||
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_GAMEWORLD_SP, 1);
|
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_GAMEWORLD_SP, 1);
|
||||||
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_IMAGE, ZoneBuilder::IsEnabled() ? 14336 : 7168);
|
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_IMAGE, ZoneBuilder::IsEnabled() ? 14336 * 2 : 7168);
|
||||||
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_LOADED_SOUND, 2700);
|
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_LOADED_SOUND, 2700 * 2);
|
||||||
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_FX, 1200);
|
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_FX, 1200 * 2);
|
||||||
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_LOCALIZE_ENTRY, 14000);
|
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_LOCALIZE_ENTRY, 14000);
|
||||||
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_XANIMPARTS, 8192);
|
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_XANIMPARTS, 8192 * 2);
|
||||||
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_XMODEL, 5125);
|
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_XMODEL, 5125 * 2);
|
||||||
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_PHYSPRESET, 128);
|
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_PHYSPRESET, 128);
|
||||||
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_PIXELSHADER, ZoneBuilder::IsEnabled() ? 0x4000 : 10000);
|
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_PIXELSHADER, ZoneBuilder::IsEnabled() ? 0x4000 : 10000);
|
||||||
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_VERTEXSHADER, ZoneBuilder::IsEnabled() ? 0x2000 : 3072);
|
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_VERTEXSHADER, ZoneBuilder::IsEnabled() ? 0x2000 : 3072);
|
||||||
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_MATERIAL, 8192);
|
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_MATERIAL, 8192 * 2);
|
||||||
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_VERTEXDECL, ZoneBuilder::IsEnabled() ? 0x400 : 196);
|
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_VERTEXDECL, ZoneBuilder::IsEnabled() ? 0x400 : 196);
|
||||||
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_WEAPON, WEAPON_LIMIT);
|
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_WEAPON, WEAPON_LIMIT);
|
||||||
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_STRINGTABLE, 800);
|
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_STRINGTABLE, 800);
|
||||||
@ -559,10 +763,11 @@ namespace Components
|
|||||||
if (ZoneBuilder::IsEnabled())
|
if (ZoneBuilder::IsEnabled())
|
||||||
{
|
{
|
||||||
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_MAP_ENTS, 10);
|
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_MAP_ENTS, 10);
|
||||||
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_XMODEL_SURFS, 8192);
|
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_XMODEL_SURFS, 8192 * 2);
|
||||||
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_TECHNIQUE_SET, 0x2000);
|
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_TECHNIQUE_SET, 0x2000);
|
||||||
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_FONT, 32);
|
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_FONT, 32);
|
||||||
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_RAWFILE, 2048);
|
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_RAWFILE, 2048);
|
||||||
|
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_LEADERBOARD, 500);
|
||||||
|
|
||||||
AssetHandler::RegisterInterface(new Assets::IFont_s());
|
AssetHandler::RegisterInterface(new Assets::IFont_s());
|
||||||
AssetHandler::RegisterInterface(new Assets::IWeapon());
|
AssetHandler::RegisterInterface(new Assets::IWeapon());
|
||||||
|
@ -41,6 +41,8 @@ namespace Components
|
|||||||
|
|
||||||
static void ExposeTemporaryAssets(bool expose);
|
static void ExposeTemporaryAssets(bool expose);
|
||||||
|
|
||||||
|
static void OffsetToAlias(Utils::Stream::Offset* offset);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static thread_local int BypassState;
|
static thread_local int BypassState;
|
||||||
static bool ShouldSearchTempAssets;
|
static bool ShouldSearchTempAssets;
|
||||||
@ -63,8 +65,6 @@ namespace Components
|
|||||||
static void FindAssetStub();
|
static void FindAssetStub();
|
||||||
static void AddAssetStub();
|
static void AddAssetStub();
|
||||||
|
|
||||||
static void OffsetToAlias(Utils::Stream::Offset* offset);
|
|
||||||
|
|
||||||
static void StoreEmptyAsset(Game::XAssetType type, const char* name);
|
static void StoreEmptyAsset(Game::XAssetType type, const char* name);
|
||||||
static void StoreEmptyAssetStub();
|
static void StoreEmptyAssetStub();
|
||||||
|
|
||||||
|
@ -320,7 +320,7 @@ namespace Components
|
|||||||
Zones::SetVersion(*version);
|
Zones::SetVersion(*version);
|
||||||
|
|
||||||
// Allow loading of codo versions
|
// Allow loading of codo versions
|
||||||
if (*version >= VERSION_ALPHA2 && *version <= 360)
|
if ((*version >= VERSION_ALPHA2 && *version <= 360) || (*version >= 423 && *version <= 461))
|
||||||
{
|
{
|
||||||
*version = XFILE_VERSION;
|
*version = XFILE_VERSION;
|
||||||
}
|
}
|
||||||
@ -369,7 +369,7 @@ namespace Components
|
|||||||
|
|
||||||
unsigned long outLen = sizeof(FastFiles::CurrentKey);
|
unsigned long outLen = sizeof(FastFiles::CurrentKey);
|
||||||
rsa_import(FastFiles::ZoneKey, sizeof(FastFiles::ZoneKey), &key);
|
rsa_import(FastFiles::ZoneKey, sizeof(FastFiles::ZoneKey), &key);
|
||||||
rsa_decrypt_key_ex(encKey, 256, FastFiles::CurrentKey.data, &outLen, nullptr, NULL, hash, (Zones::Version() >= 359 ? 1 : 2), &stat, &key);
|
rsa_decrypt_key_ex(encKey, 256, FastFiles::CurrentKey.data, &outLen, nullptr, NULL, hash, Zones::Version() >= 359 ? 1 : 2, &stat, &key);
|
||||||
rsa_free(&key);
|
rsa_free(&key);
|
||||||
|
|
||||||
ctr_start(aes, FastFiles::CurrentKey.iv, FastFiles::CurrentKey.key, sizeof(FastFiles::CurrentKey.key), 0, 0, &FastFiles::CurrentCTR);
|
ctr_start(aes, FastFiles::CurrentKey.iv, FastFiles::CurrentKey.key, sizeof(FastFiles::CurrentKey.key), 0, 0, &FastFiles::CurrentCTR);
|
||||||
@ -484,7 +484,7 @@ namespace Components
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void FastFiles::Load_XSurfaceArray(int atStreamStart, int /*count*/)
|
void FastFiles::Load_XSurfaceArray(int atStreamStart, [[maybe_unused]] int count)
|
||||||
{
|
{
|
||||||
// read the actual count from the varXModelSurfs ptr
|
// read the actual count from the varXModelSurfs ptr
|
||||||
auto surface = *reinterpret_cast<Game::XModelSurfs**>(0x0112A95C);
|
auto surface = *reinterpret_cast<Game::XModelSurfs**>(0x0112A95C);
|
||||||
|
@ -128,7 +128,7 @@ namespace Components
|
|||||||
|
|
||||||
Maps::SPMap = false;
|
Maps::SPMap = false;
|
||||||
Maps::CurrentMainZone = zoneInfo->name;
|
Maps::CurrentMainZone = zoneInfo->name;
|
||||||
|
|
||||||
Maps::CurrentDependencies.clear();
|
Maps::CurrentDependencies.clear();
|
||||||
for (auto i = Maps::DependencyList.begin(); i != Maps::DependencyList.end(); ++i)
|
for (auto i = Maps::DependencyList.begin(); i != Maps::DependencyList.end(); ++i)
|
||||||
{
|
{
|
||||||
@ -149,7 +149,7 @@ namespace Components
|
|||||||
|
|
||||||
std::vector<Game::XZoneInfo> data;
|
std::vector<Game::XZoneInfo> data;
|
||||||
Utils::Merge(&data, zoneInfo, zoneCount);
|
Utils::Merge(&data, zoneInfo, zoneCount);
|
||||||
|
|
||||||
Game::XZoneInfo team;
|
Game::XZoneInfo team;
|
||||||
team.allocFlags = zoneInfo->allocFlags;
|
team.allocFlags = zoneInfo->allocFlags;
|
||||||
team.freeFlags = zoneInfo->freeFlags;
|
team.freeFlags = zoneInfo->freeFlags;
|
||||||
@ -252,12 +252,8 @@ namespace Components
|
|||||||
asset.mapEnts->entityString = const_cast<char*>(mapEntities.data());
|
asset.mapEnts->entityString = const_cast<char*>(mapEntities.data());
|
||||||
asset.mapEnts->numEntityChars = mapEntities.size() + 1;
|
asset.mapEnts->numEntityChars = mapEntities.size() + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply new mapEnts
|
|
||||||
// This doesn't work, entities are spawned before the patch file is loaded
|
|
||||||
//Maps::OverrideMapEnts(asset.mapEnts);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is broken
|
// This is broken
|
||||||
if ((type == Game::XAssetType::ASSET_TYPE_MENU || type == Game::XAssetType::ASSET_TYPE_MENULIST) && Zones::Version() >= 359)
|
if ((type == Game::XAssetType::ASSET_TYPE_MENU || type == Game::XAssetType::ASSET_TYPE_MENULIST) && Zones::Version() >= 359)
|
||||||
{
|
{
|
||||||
@ -271,14 +267,13 @@ namespace Components
|
|||||||
Logger::Print("Waiting for database...\n");
|
Logger::Print("Waiting for database...\n");
|
||||||
while (!Game::Sys_IsDatabaseReady()) std::this_thread::sleep_for(10ms);
|
while (!Game::Sys_IsDatabaseReady()) std::this_thread::sleep_for(10ms);
|
||||||
|
|
||||||
if (!Utils::String::StartsWith(Maps::CurrentMainZone, "mp_") || Maps::SPMap)
|
if (!Game::DB_XAssetPool[Game::XAssetType::ASSET_TYPE_GAMEWORLD_MP].gameWorldMp || !Game::DB_XAssetPool[Game::XAssetType::ASSET_TYPE_GAMEWORLD_MP].gameWorldMp->name ||
|
||||||
|
!Game::DB_XAssetPool[Game::XAssetType::ASSET_TYPE_GAMEWORLD_MP].gameWorldMp->g_glassData || Maps::SPMap)
|
||||||
{
|
{
|
||||||
return Game::DB_XAssetPool[Game::XAssetType::ASSET_TYPE_GAMEWORLD_SP].gameWorldSp[0].g_glassData;
|
return Game::DB_XAssetPool[Game::XAssetType::ASSET_TYPE_GAMEWORLD_SP].gameWorldSp->g_glassData;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return Game::DB_XAssetPool[Game::XAssetType::ASSET_TYPE_GAMEWORLD_MP].gameWorldMp[0].g_glassData;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return Game::DB_XAssetPool[Game::XAssetType::ASSET_TYPE_GAMEWORLD_MP].gameWorldMp->g_glassData;
|
||||||
}
|
}
|
||||||
|
|
||||||
__declspec(naked) void Maps::GetWorldDataStub()
|
__declspec(naked) void Maps::GetWorldDataStub()
|
||||||
@ -864,6 +859,17 @@ namespace Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Maps::G_SpawnTurretHook(Game::gentity_s* ent, int unk, int unk2)
|
||||||
|
{
|
||||||
|
if (Maps::CurrentMainZone == "mp_backlot_sh"s || Maps::CurrentMainZone == "mp_con_spring"s ||
|
||||||
|
Maps::CurrentMainZone == "mp_mogadishu_sh"s || Maps::CurrentMainZone == "mp_nightshift_sh"s)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Utils::Hook::Call<void(Game::gentity_s*, int, int)>(0x408910)(ent, unk, unk2);
|
||||||
|
}
|
||||||
|
|
||||||
Maps::Maps()
|
Maps::Maps()
|
||||||
{
|
{
|
||||||
Dvar::OnInit([]()
|
Dvar::OnInit([]()
|
||||||
@ -874,8 +880,8 @@ namespace Components
|
|||||||
Maps::AddDlc({ 1, "Stimulus Pack", {"mp_complex", "mp_compact", "mp_storm", "mp_overgrown", "mp_crash"} });
|
Maps::AddDlc({ 1, "Stimulus Pack", {"mp_complex", "mp_compact", "mp_storm", "mp_overgrown", "mp_crash"} });
|
||||||
Maps::AddDlc({ 2, "Resurgence Pack", {"mp_abandon", "mp_vacant", "mp_trailerpark", "mp_strike", "mp_fuel2"} });
|
Maps::AddDlc({ 2, "Resurgence Pack", {"mp_abandon", "mp_vacant", "mp_trailerpark", "mp_strike", "mp_fuel2"} });
|
||||||
Maps::AddDlc({ 3, "Nuketown", {"mp_nuked"} });
|
Maps::AddDlc({ 3, "Nuketown", {"mp_nuked"} });
|
||||||
Maps::AddDlc({ 4, "Classics Pack", {"mp_cross_fire", "mp_cargoship", "mp_bloc"} });
|
Maps::AddDlc({ 4, "Classics Pack #1", {"mp_cross_fire", "mp_cargoship", "mp_bloc"} });
|
||||||
Maps::AddDlc({ 5, "Classics Pack", {"mp_killhouse", "mp_bog_sh"} });
|
Maps::AddDlc({ 5, "Classics Pack #2", {"mp_killhouse", "mp_bog_sh"} });
|
||||||
Maps::AddDlc({ 6, "Freighter", {"mp_cargoship_sh"} });
|
Maps::AddDlc({ 6, "Freighter", {"mp_cargoship_sh"} });
|
||||||
Maps::AddDlc({ 7, "Resurrection Pack", {"mp_shipment_long", "mp_rust_long", "mp_firingrange"} });
|
Maps::AddDlc({ 7, "Resurrection Pack", {"mp_shipment_long", "mp_rust_long", "mp_firingrange"} });
|
||||||
Maps::AddDlc({ 8, "Recycled Pack", {"mp_bloc_sh", "mp_crash_tropical", "mp_estate_tropical", "mp_fav_tropical", "mp_storm_spring"} });
|
Maps::AddDlc({ 8, "Recycled Pack", {"mp_bloc_sh", "mp_crash_tropical", "mp_estate_tropical", "mp_fav_tropical", "mp_storm_spring"} });
|
||||||
@ -900,6 +906,10 @@ namespace Components
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// disable turrets on CoD:OL 448+ maps for now
|
||||||
|
Utils::Hook(0x5EE577, Maps::G_SpawnTurretHook, HOOK_CALL).install()->quick();
|
||||||
|
Utils::Hook(0x44A4D5, Maps::G_SpawnTurretHook, HOOK_CALL).install()->quick();
|
||||||
|
|
||||||
//#define SORT_SMODELS
|
//#define SORT_SMODELS
|
||||||
#if !defined(DEBUG) || !defined(SORT_SMODELS)
|
#if !defined(DEBUG) || !defined(SORT_SMODELS)
|
||||||
// Don't sort static models
|
// Don't sort static models
|
||||||
|
@ -123,5 +123,6 @@ namespace Components
|
|||||||
static Game::dvar_t* GetSpecularDvar();
|
static Game::dvar_t* GetSpecularDvar();
|
||||||
static void SetSpecularStub1();
|
static void SetSpecularStub1();
|
||||||
static void SetSpecularStub2();
|
static void SetSpecularStub2();
|
||||||
|
static void G_SpawnTurretHook(Game::gentity_s* ent, int unk, int unk2);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -9,6 +9,13 @@ namespace Components
|
|||||||
class Zones : public Component
|
class Zones : public Component
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
struct FileData
|
||||||
|
{
|
||||||
|
std::uint32_t readPos;
|
||||||
|
std::uint32_t len;
|
||||||
|
std::string fileContents;
|
||||||
|
};
|
||||||
|
|
||||||
Zones();
|
Zones();
|
||||||
~Zones();
|
~Zones();
|
||||||
|
|
||||||
@ -17,6 +24,7 @@ namespace Components
|
|||||||
static int Version() { return Zones::ZoneVersion; };
|
static int Version() { return Zones::ZoneVersion; };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
static int ZoneVersion;
|
static int ZoneVersion;
|
||||||
|
|
||||||
static int FxEffectIndex;
|
static int FxEffectIndex;
|
||||||
@ -61,6 +69,36 @@ namespace Components
|
|||||||
static void LoadImpactFxArray();
|
static void LoadImpactFxArray();
|
||||||
static int ImpactFxArrayCount();
|
static int ImpactFxArrayCount();
|
||||||
static void LoadPathDataConstant();
|
static void LoadPathDataConstant();
|
||||||
|
static void GetCurrentAssetTypeStub();
|
||||||
|
static int LoadRandomFxGarbage(bool atStreamStart, char* buffer, int size);
|
||||||
|
static int LoadGfxXSurfaceArray(bool atStreamStart, char* buffer, int size);
|
||||||
|
static int LoadGfxXSurfaceExtraData(bool atStreamStart);
|
||||||
|
static int LoadGfxReflectionProbes(bool atStreamStart, char* buffer, int size);
|
||||||
|
static void LoadGfxLightMapExtraData();
|
||||||
|
static void LoadXModelColSurfPtr();
|
||||||
static int PathDataSize();
|
static int PathDataSize();
|
||||||
|
static int LoadMaterialTechniqueArray(bool atStreamStart, int count);
|
||||||
|
static int LoadMapEnts(bool atStreamStart, Game::MapEnts* buffer, int size);
|
||||||
|
static void Load_ClipInfo(bool atStreamStart);
|
||||||
|
static int LoadClipMap(bool atStreamStart);
|
||||||
|
static uint32_t HashCRC32StringInt(const std::string& Value, uint32_t Initial);
|
||||||
|
static std::unordered_map<int, Zones::FileData> fileDataMap;
|
||||||
|
static std::mutex fileDataMutex;
|
||||||
|
static int FS_FOpenFileReadForThreadOriginal(const char*, int*, int);
|
||||||
|
static int FS_FOpenFileReadForThreadHook(const char* file, int* filePointer, int thread);
|
||||||
|
static int FS_ReadOriginal(void*, size_t, int);
|
||||||
|
static int FS_ReadHook(void* buffer, size_t size, int filePointer);
|
||||||
|
static void FS_FCloseFileOriginal(int);
|
||||||
|
static void FS_FCloseFileHook(int filePointer);
|
||||||
|
static std::uint32_t FS_SeekOriginal(int, int, int);
|
||||||
|
static std::uint32_t FS_SeekHook(int fileHandle, int seekPosition, int seekOrigin);
|
||||||
|
static void LoadMapTriggersModelPointer();
|
||||||
|
static void LoadMapTriggersHullPointer();
|
||||||
|
static void LoadMapTriggersSlabPointer();
|
||||||
|
static void LoadFxWorldAsset(Game::FxWorld** asset);
|
||||||
|
static void LoadXModelAsset(Game::XModel** asset);
|
||||||
|
static void LoadMaterialAsset(Game::Material** asset);
|
||||||
|
static void LoadTracerDef(bool atStreamStart, Game::TracerDef* tracer, int size);
|
||||||
|
static void LoadTracerDefFxEffect();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,26 @@
|
|||||||
|
|
||||||
namespace Game
|
namespace Game
|
||||||
{
|
{
|
||||||
|
std::vector<std::string> Sys_ListFilesWrapper(const std::string& directory, const std::string& extension)
|
||||||
|
{
|
||||||
|
auto fileCount = 0;
|
||||||
|
auto files = Game::Sys_ListFiles(directory.data(), extension.data(), 0, &fileCount, 0);
|
||||||
|
|
||||||
|
std::vector<std::string> result;
|
||||||
|
|
||||||
|
for (auto i = 0; i < fileCount; i++)
|
||||||
|
{
|
||||||
|
if (files[i])
|
||||||
|
{
|
||||||
|
result.push_back(files[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Game::FS_FreeFileList(files);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
AddRefToObject_t AddRefToObject = AddRefToObject_t(0x61C360);
|
AddRefToObject_t AddRefToObject = AddRefToObject_t(0x61C360);
|
||||||
AllocObject_t AllocObject = AllocObject_t(0x434320);
|
AllocObject_t AllocObject = AllocObject_t(0x434320);
|
||||||
|
|
||||||
|
@ -2,6 +2,26 @@
|
|||||||
|
|
||||||
namespace Game
|
namespace Game
|
||||||
{
|
{
|
||||||
|
template <typename T> static void DB_ConvertOffsetToPointer(T* pointer)
|
||||||
|
{
|
||||||
|
Utils::Hook::Call<void(T*)>(0x4A82B0)(pointer);
|
||||||
|
}
|
||||||
|
template <typename T> static T** DB_InsertPointer()
|
||||||
|
{
|
||||||
|
static auto DB_InsertPointer_Address = 0x43B290;
|
||||||
|
T** retval = nullptr;
|
||||||
|
|
||||||
|
__asm
|
||||||
|
{
|
||||||
|
call DB_InsertPointer_Address;
|
||||||
|
mov retval, eax;
|
||||||
|
}
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> Sys_ListFilesWrapper(const std::string& directory, const std::string& extension);
|
||||||
|
|
||||||
typedef void(__cdecl * AddRefToObject_t)(unsigned int id);
|
typedef void(__cdecl * AddRefToObject_t)(unsigned int id);
|
||||||
extern AddRefToObject_t AddRefToObject;
|
extern AddRefToObject_t AddRefToObject;
|
||||||
|
|
||||||
@ -319,7 +339,7 @@ namespace Game
|
|||||||
typedef void(__cdecl * LargeLocalInit_t)();
|
typedef void(__cdecl * LargeLocalInit_t)();
|
||||||
extern LargeLocalInit_t LargeLocalInit;
|
extern LargeLocalInit_t LargeLocalInit;
|
||||||
|
|
||||||
typedef bool(__cdecl * Load_Stream_t)(bool atStreamStart, const void *ptr, int size);
|
typedef bool(__cdecl * Load_Stream_t)(bool atStreamStart, const void *ptr, unsigned int size);
|
||||||
extern Load_Stream_t Load_Stream;
|
extern Load_Stream_t Load_Stream;
|
||||||
|
|
||||||
typedef void(__cdecl * Load_XString_t)(bool atStreamStart);
|
typedef void(__cdecl * Load_XString_t)(bool atStreamStart);
|
||||||
|
Loading…
Reference in New Issue
Block a user