IW4Of Fixes (#775)

Co-authored-by: Louvenarde <louve@louve.systems>
Co-authored-by: FutureRave <edoardo.sanguineti222@gmail.com>
This commit is contained in:
Louve 2023-02-17 12:26:40 +01:00 committed by GitHub
parent d1f6f1db8b
commit 4103e4d174
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 87 additions and 24 deletions

@ -1 +1 @@
Subproject commit 2dde0c2103aab094f27b3c1daa790995df54faef Subproject commit 6ef68c8535b60c681b179608f0c95fe0893e8937

View File

@ -17,7 +17,8 @@ end
function iw4_open_formats.project() function iw4_open_formats.project()
project "iw4-open-formats" project "iw4-open-formats"
language "C++" language "C++"
cppdialect "C++latest"
iw4_open_formats.includes() iw4_open_formats.includes()
pchheader "std_include.hpp" pchheader "std_include.hpp"

View File

@ -22,7 +22,34 @@ namespace Assets
void IMaterialTechniqueSet::loadFromDisk(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) void IMaterialTechniqueSet::loadFromDisk(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder)
{ {
header->techniqueSet = builder->getIW4OfApi()->read<Game::MaterialTechniqueSet>(Game::XAssetType::ASSET_TYPE_TECHNIQUE_SET, name); header->techniqueSet = builder->getIW4OfApi()->read<Game::MaterialTechniqueSet>(Game::ASSET_TYPE_TECHNIQUE_SET, name);
auto ptr = header->techniqueSet;
if (!ptr)
{
return;
}
while (ptr->remappedTechniqueSet && ptr->remappedTechniqueSet != ptr)
{
ptr = ptr->remappedTechniqueSet;
builder->loadAsset(Game::ASSET_TYPE_TECHNIQUE_SET, ptr, false);
for (size_t i = 0; i < Game::TECHNIQUE_COUNT; i++)
{
const auto technique = ptr->techniques[i];
if (technique)
{
for (size_t j = 0; j < technique->passCount; j++)
{
const auto pass = &technique->passArray[j];
builder->loadAsset(Game::ASSET_TYPE_VERTEXDECL, pass->vertexDecl, true);
builder->loadAsset(Game::ASSET_TYPE_PIXELSHADER, pass->pixelShader, true);
builder->loadAsset(Game::ASSET_TYPE_VERTEXSHADER, pass->vertexShader, true);
}
}
}
}
} }
void IMaterialTechniqueSet::mark(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) void IMaterialTechniqueSet::mark(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder)

View File

@ -572,7 +572,7 @@ namespace Assets
} }
} }
builder->loadAsset(Game::XAssetType::ASSET_TYPE_MAP_ENTS, asset); builder->loadAsset(Game::XAssetType::ASSET_TYPE_MAP_ENTS, asset->mapEnts);
} }
void IclipMap_t::load(Game::XAssetHeader* header, const std::string& _name, Components::ZoneBuilder::Zone* builder) void IclipMap_t::load(Game::XAssetHeader* header, const std::string& _name, Components::ZoneBuilder::Zone* builder)

View File

@ -666,12 +666,25 @@ namespace Components
return Utils::Hook::Call<bool(Game::gentity_s*)>(0x5050C0)(ent); return Utils::Hook::Call<bool(Game::gentity_s*)>(0x5050C0)(ent);
} }
int16 Maps::CM_TriggerModelBounds(int modelPointer, Game::Bounds* bounds) { unsigned short Maps::CM_TriggerModelBounds_Hk(unsigned int triggerIndex, Game::Bounds* bounds)
#ifdef DEBUG {
Game::MapEnts* ents = *reinterpret_cast<Game::MapEnts**>(0x1AA651C); // Use me for debugging
(void)ents; auto* ents = *reinterpret_cast<Game::MapEnts**>(0x1AA651C); // Use me for debugging
#endif
return Utils::Hook::Call<int16(int, Game::Bounds*)>(0x4416C0)(modelPointer, bounds); if (ents)
{
if (triggerIndex >= ents->trigger.count)
{
Logger::Error(Game::errorParm_t::ERR_DROP, "Invalid trigger index ({}) in entities exceeds the maximum trigger count ({}) defined in the clipmap. Check your map ents, or your clipmap!", triggerIndex, ents->trigger.count);
return 0;
}
else
{
return Utils::Hook::Call<unsigned short(int, Game::Bounds*)>(0x4416C0)(triggerIndex, bounds);
}
}
return 0;
} }
Maps::Maps() Maps::Maps()
@ -714,11 +727,13 @@ namespace Components
Utils::Hook(0x5EE577, Maps::G_SpawnTurretHook, HOOK_CALL).install()->quick(); Utils::Hook(0x5EE577, Maps::G_SpawnTurretHook, HOOK_CALL).install()->quick();
Utils::Hook(0x44A4D5, Maps::G_SpawnTurretHook, HOOK_CALL).install()->quick(); Utils::Hook(0x44A4D5, Maps::G_SpawnTurretHook, HOOK_CALL).install()->quick();
// Catch trigger errors before they're critical
Utils::Hook(0x5050D4, Maps::CM_TriggerModelBounds_Hk, HOOK_CALL).install()->quick();
#ifdef DEBUG #ifdef DEBUG
// Check trigger models // Check trigger models
Utils::Hook(0x5FC0F1, Maps::SV_SetTriggerModelHook, HOOK_CALL).install()->quick(); Utils::Hook(0x5FC0F1, Maps::SV_SetTriggerModelHook, HOOK_CALL).install()->quick();
Utils::Hook(0x5FC2671, Maps::SV_SetTriggerModelHook, HOOK_CALL).install()->quick(); Utils::Hook(0x5FC2671, Maps::SV_SetTriggerModelHook, HOOK_CALL).install()->quick();
Utils::Hook(0x5050D4, Maps::CM_TriggerModelBounds, HOOK_CALL).install()->quick();
#endif #endif
// //

View File

@ -121,6 +121,6 @@ namespace Components
static void G_SpawnTurretHook(Game::gentity_s* ent, int unk, int unk2); static void G_SpawnTurretHook(Game::gentity_s* ent, int unk, int unk2);
static bool SV_SetTriggerModelHook(Game::gentity_s* ent); static bool SV_SetTriggerModelHook(Game::gentity_s* ent);
static int16 CM_TriggerModelBounds(int brushModelPointer, Game::Bounds* bounds); static unsigned short CM_TriggerModelBounds_Hk(unsigned int brushModelPointer, Game::Bounds* bounds);
}; };
} }

View File

@ -29,9 +29,9 @@ namespace Components
zoneName(name), zoneName(name),
dataMap("zone_source/" + name + ".csv"), dataMap("zone_source/" + name + ".csv"),
branding{nullptr}, branding{nullptr},
assetDepth(0) assetDepth(0),
iw4ofApi(getIW4OfApiParams())
{ {
this->initializeIW4OfApi();
} }
ZoneBuilder::Zone::~Zone() ZoneBuilder::Zone::~Zone()
@ -535,18 +535,21 @@ namespace Components
// Add branding asset // Add branding asset
void ZoneBuilder::Zone::addBranding() void ZoneBuilder::Zone::addBranding()
{ {
constexpr auto* data = "Built using the IW4x Zone:B:uilder Version 4"; static std::string zoneBranding;
auto dataLen = std::strlen(data); // + 1 is added by the save code
this->branding = {this->zoneName.data(), 0, static_cast<int>(dataLen), data}; const auto now = std::chrono::system_clock::now();
zoneBranding = std::format("Built using the IW4x ZoneBuilder! {:%d-%m-%Y %H:%M:%OS}", now);
auto brandingLen = zoneBranding.size(); // + 1 is added by the save code
if (this->findAsset(Game::XAssetType::ASSET_TYPE_RAWFILE, this->branding.name) != -1) this->branding = {this->zoneName.data(), 0, static_cast<int>(brandingLen), zoneBranding.data()};
if (this->findAsset(Game::ASSET_TYPE_RAWFILE, this->branding.name) != -1)
{ {
Logger::Error(Game::ERR_FATAL, "Unable to add branding. Asset '{}' already exists!", this->branding.name); Logger::Error(Game::ERR_FATAL, "Unable to add branding. Asset '{}' already exists!", this->branding.name);
} }
Game::XAssetHeader header = { &this->branding }; Game::XAssetHeader header = { &this->branding };
Game::XAsset brandingAsset = { Game::XAssetType::ASSET_TYPE_RAWFILE, header }; Game::XAsset brandingAsset = { Game::ASSET_TYPE_RAWFILE, header };
this->loadedAssets.push_back(brandingAsset); this->loadedAssets.push_back(brandingAsset);
} }
@ -757,7 +760,7 @@ namespace Components
return header; return header;
} }
void ZoneBuilder::Zone::initializeIW4OfApi() iw4of::params_t ZoneBuilder::Zone::getIW4OfApiParams()
{ {
iw4of::params_t params; iw4of::params_t params;
@ -787,7 +790,7 @@ namespace Components
switch (t) switch (t)
{ {
case iw4of::params_t::P_ERR: case iw4of::params_t::P_ERR:
Logger::PrintError(Game::CON_CHANNEL_ERROR, "{}", message); Logger::Error(Game::ERR_FATAL, "{}", message);
break; break;
case iw4of::params_t::P_WARN: case iw4of::params_t::P_WARN:
Logger::Print("{}", message); Logger::Print("{}", message);
@ -795,9 +798,16 @@ namespace Components
} }
}; };
params.work_directory = (*Game::fs_basepath)->current.string; if (*Game::fs_basepath && *Game::fs_gameDirVar)
{
params.work_directory = std::format("{}/{}", (*Game::fs_basepath)->current.string, (*Game::fs_gameDirVar)->current.string);
}
else
{
Logger::Error(Game::ERR_FATAL, "Missing FS Game directory or basepath directory!");
}
this->iw4ofApi = iw4of::api{ params }; return params;
} }
int ZoneBuilder::StoreTexture(Game::GfxImageLoadDef **loadDef, Game::GfxImage *image) int ZoneBuilder::StoreTexture(Game::GfxImageLoadDef **loadDef, Game::GfxImage *image)

View File

@ -90,7 +90,7 @@ namespace Components
void addBranding(); void addBranding();
void initializeIW4OfApi(); iw4of::params_t getIW4OfApiParams();
uint32_t safeGetPointer(const void* pointer); uint32_t safeGetPointer(const void* pointer);

View File

@ -48,6 +48,9 @@ namespace Game
const char* DB_GetXAssetName(XAsset* asset) const char* DB_GetXAssetName(XAsset* asset)
{ {
if (!asset) return ""; if (!asset) return "";
assert(asset->header.data);
return DB_GetXAssetNameHandlers[asset->type](&asset->header); return DB_GetXAssetNameHandlers[asset->type](&asset->header);
} }

View File

@ -7801,6 +7801,13 @@ namespace Game
R_RENDERTARGET_NONE = 0xD, R_RENDERTARGET_NONE = 0xD,
}; };
struct GfxDrawPrimArgs
{
int vertexCount;
int triCount;
int baseIndex;
};
struct GfxCmdBufState struct GfxCmdBufState
{ {
char refSamplerState[16]; char refSamplerState[16];