Merge pull request #71 from Rackover/fix_cod4_trigs_iw4xcompatible
Enhance CoD4 map porting
This commit is contained in:
commit
640db8a3e6
2
deps/json11
vendored
2
deps/json11
vendored
@ -1 +1 @@
|
|||||||
Subproject commit 2df9473fb3605980db55ecddf34392a2e832ad35
|
Subproject commit e2e3a11e99672b018e0e0657867e6a3439e180cf
|
2
deps/libtomcrypt
vendored
2
deps/libtomcrypt
vendored
@ -1 +1 @@
|
|||||||
Subproject commit 910d6252770f1e517d9ed02dc0549a1d61dfe159
|
Subproject commit 1937f412605e1b04ddb41ef9c2f2f0aab7e61548
|
2
deps/libtommath
vendored
2
deps/libtommath
vendored
@ -1 +1 @@
|
|||||||
Subproject commit eda0bd6ae5705ab90b866dfb52c5f15c23687f81
|
Subproject commit 6ac0b0c1b69b9a88e1b3b3002c2e3a9062ae99b4
|
2
deps/protobuf
vendored
2
deps/protobuf
vendored
@ -1 +1 @@
|
|||||||
Subproject commit df2bce345d4bc8cdc3eba2a866e11e79e1fff4df
|
Subproject commit 63cfdafacba6141717a2df97fc123dc0c14ba7c4
|
2
deps/zlib
vendored
2
deps/zlib
vendored
@ -1 +1 @@
|
|||||||
Subproject commit 53ce2713117ef2a8ed682d77b944df991c499252
|
Subproject commit d71dc66fa8a153fb6e7c626847095d9697a6cf42
|
@ -456,10 +456,7 @@ workspace "iw4x"
|
|||||||
--iw4mvm.project()
|
--iw4mvm.project()
|
||||||
|
|
||||||
workspace "*"
|
workspace "*"
|
||||||
buildoptions {
|
cppdialect "C++17"
|
||||||
"/std:c++latest"
|
|
||||||
}
|
|
||||||
systemversion "latest"
|
|
||||||
defines { "_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS" }
|
defines { "_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS" }
|
||||||
|
|
||||||
rule "ProtobufCompiler"
|
rule "ProtobufCompiler"
|
||||||
|
@ -7,12 +7,13 @@ namespace Assets
|
|||||||
void IFxEffectDef::load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder)
|
void IFxEffectDef::load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder)
|
||||||
{
|
{
|
||||||
if (!header->data) this->loadEfx(header, name, builder); // Check if we have an editor fx
|
if (!header->data) this->loadEfx(header, name, builder); // Check if we have an editor fx
|
||||||
if (!header->data /*&& !builder->isPrimaryAsset()*/) this->loadNative(header, name, builder); // Check if there is a native one
|
|
||||||
if (!header->data) this->loadBinary(header, name, builder); // Check if we need to import a new one into the game
|
if (!header->data) this->loadBinary(header, name, builder); // Check if we need to import a new one into the game
|
||||||
|
if (!header->data /*&& !builder->isPrimaryAsset()*/) this->loadNative(header, name, builder); // Check if there is a native one
|
||||||
}
|
}
|
||||||
|
|
||||||
void IFxEffectDef::loadFxElemVisuals(Game::FxElemVisuals* visuals, char elemType, Components::ZoneBuilder::Zone* builder, Utils::Stream::Reader* reader)
|
void IFxEffectDef::loadFxElemVisuals(Game::FxElemVisuals* visuals, char elemType, Components::ZoneBuilder::Zone* builder, Utils::Stream::Reader* reader)
|
||||||
{
|
{
|
||||||
|
|
||||||
switch (elemType)
|
switch (elemType)
|
||||||
{
|
{
|
||||||
case Game::FX_ELEM_TYPE_MODEL:
|
case Game::FX_ELEM_TYPE_MODEL:
|
||||||
@ -34,10 +35,7 @@ namespace Assets
|
|||||||
if (visuals->soundName)
|
if (visuals->soundName)
|
||||||
{
|
{
|
||||||
visuals->soundName = reader->readCString();
|
visuals->soundName = reader->readCString();
|
||||||
visuals->soundName = "null";
|
|
||||||
Components::Logger::Print("Unable to load sounds yet!\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ namespace Assets
|
|||||||
{
|
{
|
||||||
void ILoadedSound::load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder)
|
void ILoadedSound::load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder)
|
||||||
{
|
{
|
||||||
Components::FileSystem::File soundFile(Utils::String::VA("sounds/%s", name.data()));
|
Components::FileSystem::File soundFile(Utils::String::VA("loaded_sound/%s", name.data()));
|
||||||
if (!soundFile.exists())
|
if (!soundFile.exists())
|
||||||
{
|
{
|
||||||
header->loadSnd = Components::AssetHandler::FindOriginalAsset(this->getType(), name.data()).loadSnd;
|
header->loadSnd = Components::AssetHandler::FindOriginalAsset(this->getType(), name.data()).loadSnd;
|
||||||
@ -60,8 +60,8 @@ namespace Assets
|
|||||||
}
|
}
|
||||||
|
|
||||||
sound->sound.info.channels = reader.read<short>();
|
sound->sound.info.channels = reader.read<short>();
|
||||||
sound->sound.info.samples = reader.read<int>();
|
|
||||||
sound->sound.info.rate = reader.read<int>();
|
sound->sound.info.rate = reader.read<int>();
|
||||||
|
sound->sound.info.samples = reader.read<int>();
|
||||||
sound->sound.info.block_size = reader.read<short>();
|
sound->sound.info.block_size = reader.read<short>();
|
||||||
sound->sound.info.bits = reader.read<short>();
|
sound->sound.info.bits = reader.read<short>();
|
||||||
|
|
||||||
|
@ -29,6 +29,33 @@ namespace Assets
|
|||||||
"_add_lin_nofog",
|
"_add_lin_nofog",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
std::map<std::string, std::string> techSetCorrespondance = {
|
||||||
|
{"effect", "effect_blend"},
|
||||||
|
{"effect", "effect_blend"},
|
||||||
|
{"effect_nofog", "effect_blend_nofog"},
|
||||||
|
{"effect_zfeather", "effect_zfeather_blend"},
|
||||||
|
|
||||||
|
{"wc_unlit_add", "wc_unlit_add_lin"},
|
||||||
|
{"wc_unlit_multiply", "wc_unlit_multiply_lin"},
|
||||||
|
{"wc_unlit_falloff_add", "wc_unlit_falloff_add_lin_ua"},
|
||||||
|
{"wc_unlit", "wc_unlit_add_lin"},
|
||||||
|
{"wc_unlit_alphatest", "wc_unlit_blend_lin_ua"},
|
||||||
|
{"wc_unlit_multiply_lin", "wc_unlit_multiply_lin"},
|
||||||
|
{"wc_unlit_blend", "wc_unlit_blend_lin"},
|
||||||
|
{"wc_unlit_replace", "wc_unlit_replace_lin"},
|
||||||
|
|
||||||
|
{"mc_unlit_replace", "mc_unlit_replace_lin"},
|
||||||
|
{"mc_unlit_nofog", "mc_unlit_blend_nofog_ua"},
|
||||||
|
{"mc_unlit", "mc_unlit_blend_lin"},
|
||||||
|
{"mc_unlit_alphatest", "mc_unlit_blend_lin"}
|
||||||
|
/*,
|
||||||
|
{"", ""},
|
||||||
|
{"", ""},
|
||||||
|
{"", ""},
|
||||||
|
{"", ""},
|
||||||
|
{"", ""},*/
|
||||||
|
};
|
||||||
|
|
||||||
Components::FileSystem::File materialFile(Utils::String::VA("materials/%s.iw4xMaterial", name.data()));
|
Components::FileSystem::File materialFile(Utils::String::VA("materials/%s.iw4xMaterial", name.data()));
|
||||||
if (!materialFile.exists()) return;
|
if (!materialFile.exists()) return;
|
||||||
|
|
||||||
@ -185,12 +212,14 @@ namespace Assets
|
|||||||
if (!t1->techniques[i] && !t2->techniques[i]) continue;;
|
if (!t1->techniques[i] && !t2->techniques[i]) continue;;
|
||||||
if (!t1->techniques[i] || !t2->techniques[i]) return false;
|
if (!t1->techniques[i] || !t2->techniques[i]) return false;
|
||||||
|
|
||||||
if (t1->techniques[i]->flags != t1->techniques[i]->flags) return false;
|
// Apparently, this is really not that important
|
||||||
|
//if (t1->techniques[i]->flags != t2->techniques[i]->flags) return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
Game::DB_EnumXAssetEntries(Game::XAssetType::ASSET_TYPE_MATERIAL, [asset, techsetMatches](Game::XAssetEntry* entry)
|
Game::DB_EnumXAssetEntries(Game::XAssetType::ASSET_TYPE_MATERIAL, [asset, techsetMatches](Game::XAssetEntry* entry)
|
||||||
{
|
{
|
||||||
if (!replacementFound)
|
if (!replacementFound)
|
||||||
@ -209,8 +238,52 @@ namespace Assets
|
|||||||
|
|
||||||
if (!replacementFound && asset->techniqueSet)
|
if (!replacementFound && asset->techniqueSet)
|
||||||
{
|
{
|
||||||
|
|
||||||
Components::Logger::Print("No replacement found for material %s with techset %s\n", asset->info.name, asset->techniqueSet->name);
|
Components::Logger::Print("No replacement found for material %s with techset %s\n", asset->info.name, asset->techniqueSet->name);
|
||||||
|
std::string techName = asset->techniqueSet->name;
|
||||||
|
if (techSetCorrespondance.find(techName) != techSetCorrespondance.end()) {
|
||||||
|
auto iw4TechSetName = techSetCorrespondance[techName];
|
||||||
|
Game::XAssetEntry* iw4TechSet = Game::DB_FindXAssetEntry(Game::XAssetType::ASSET_TYPE_TECHNIQUE_SET, iw4TechSetName.data());
|
||||||
|
|
||||||
|
if (iw4TechSet)
|
||||||
|
{
|
||||||
|
Game::DB_EnumXAssetEntries(Game::XAssetType::ASSET_TYPE_MATERIAL, [asset, iw4TechSet](Game::XAssetEntry* entry)
|
||||||
|
{
|
||||||
|
if (!replacementFound)
|
||||||
|
{
|
||||||
|
Game::XAssetHeader header = entry->asset.header;
|
||||||
|
|
||||||
|
if (header.material->techniqueSet == iw4TechSet->asset.header.techniqueSet)
|
||||||
|
{
|
||||||
|
Components::Logger::Print("Material %s with techset %s has been mapped to %s (last chance!)\n", asset->info.name, asset->techniqueSet->name, header.material->techniqueSet->name);
|
||||||
|
asset->info.sortKey = header.material->info.sortKey;
|
||||||
|
asset->techniqueSet = iw4TechSet->asset.header.techniqueSet;
|
||||||
|
|
||||||
|
// this is terrible!
|
||||||
|
asset->stateBitsCount = header.material->stateBitsCount;
|
||||||
|
asset->stateBitsTable = header.material->stateBitsTable;
|
||||||
|
std::memcpy(asset->stateBitsEntry, header.material->stateBitsEntry, 48);
|
||||||
|
asset->constantCount = header.material->constantCount;
|
||||||
|
asset->constantTable = header.material->constantTable;
|
||||||
|
|
||||||
|
replacementFound = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, false, false);
|
||||||
|
|
||||||
|
if (!replacementFound)
|
||||||
|
{
|
||||||
|
Components::Logger::Print("Could not find any loaded material with techset %s (in replacement of %s), so I cannot set the sortkey for material %s\n", iw4TechSetName.data(), asset->techniqueSet->name, asset->info.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Components::Logger::Print("Could not find any loaded techset with iw4 name %s for iw3 techset %s\n", iw4TechSetName.data(), asset->techniqueSet->name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Components::Logger::Print("Could not match iw3 techset %s with any of the techsets I know! This is a critical error, there's a good chance the map will not be playable.\n", techName.data());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!reader.end())
|
if (!reader.end())
|
||||||
|
@ -15,9 +15,9 @@ namespace Assets
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IWeapon::mark(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder)
|
void IWeapon::mark(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder)
|
||||||
{
|
{
|
||||||
Game::WeaponCompleteDef* asset = header.weapon;
|
Game::WeaponCompleteDef* asset = header.weapon;
|
||||||
|
|
||||||
// convert all script strings
|
// convert all script strings
|
||||||
if (asset->hideTags)
|
if (asset->hideTags)
|
||||||
@ -119,7 +119,80 @@ namespace Assets
|
|||||||
if (asset->weapDef->projBeaconEffect) builder->loadAsset(Game::XAssetType::ASSET_TYPE_FX, asset->weapDef->projBeaconEffect);
|
if (asset->weapDef->projBeaconEffect) builder->loadAsset(Game::XAssetType::ASSET_TYPE_FX, asset->weapDef->projBeaconEffect);
|
||||||
if (asset->weapDef->projIgnitionEffect) builder->loadAsset(Game::XAssetType::ASSET_TYPE_FX, asset->weapDef->projIgnitionEffect);
|
if (asset->weapDef->projIgnitionEffect) builder->loadAsset(Game::XAssetType::ASSET_TYPE_FX, asset->weapDef->projIgnitionEffect);
|
||||||
if (asset->weapDef->turretOverheatEffect) builder->loadAsset(Game::XAssetType::ASSET_TYPE_FX, asset->weapDef->turretOverheatEffect);
|
if (asset->weapDef->turretOverheatEffect) builder->loadAsset(Game::XAssetType::ASSET_TYPE_FX, asset->weapDef->turretOverheatEffect);
|
||||||
}
|
|
||||||
|
#define LoadWeapSound(sound) if (asset->weapDef->##sound##) builder->loadAsset(Game::XAssetType::ASSET_TYPE_SOUND, asset->weapDef->##sound##)
|
||||||
|
|
||||||
|
LoadWeapSound(pickupSound);
|
||||||
|
LoadWeapSound(pickupSoundPlayer);
|
||||||
|
LoadWeapSound(ammoPickupSound);
|
||||||
|
LoadWeapSound(ammoPickupSoundPlayer);
|
||||||
|
LoadWeapSound(projectileSound);
|
||||||
|
LoadWeapSound(pullbackSound);
|
||||||
|
LoadWeapSound(pullbackSoundPlayer);
|
||||||
|
LoadWeapSound(fireSound);
|
||||||
|
LoadWeapSound(fireSoundPlayer);
|
||||||
|
LoadWeapSound(fireSoundPlayerAkimbo);
|
||||||
|
LoadWeapSound(fireLoopSound);
|
||||||
|
LoadWeapSound(fireLoopSoundPlayer);
|
||||||
|
LoadWeapSound(fireStopSound);
|
||||||
|
LoadWeapSound(fireStopSoundPlayer);
|
||||||
|
LoadWeapSound(fireLastSound);
|
||||||
|
LoadWeapSound(fireLastSoundPlayer);
|
||||||
|
LoadWeapSound(emptyFireSound);
|
||||||
|
LoadWeapSound(emptyFireSoundPlayer);
|
||||||
|
LoadWeapSound(meleeSwipeSound);
|
||||||
|
LoadWeapSound(meleeSwipeSoundPlayer);
|
||||||
|
LoadWeapSound(meleeHitSound);
|
||||||
|
LoadWeapSound(meleeMissSound);
|
||||||
|
LoadWeapSound(rechamberSound);
|
||||||
|
LoadWeapSound(rechamberSoundPlayer);
|
||||||
|
LoadWeapSound(reloadSound);
|
||||||
|
LoadWeapSound(reloadSoundPlayer);
|
||||||
|
LoadWeapSound(reloadEmptySound);
|
||||||
|
LoadWeapSound(reloadEmptySoundPlayer);
|
||||||
|
LoadWeapSound(reloadStartSound);
|
||||||
|
LoadWeapSound(reloadStartSoundPlayer);
|
||||||
|
LoadWeapSound(reloadEndSound);
|
||||||
|
LoadWeapSound(reloadEndSoundPlayer);
|
||||||
|
LoadWeapSound(detonateSound);
|
||||||
|
LoadWeapSound(detonateSoundPlayer);
|
||||||
|
LoadWeapSound(nightVisionWearSound);
|
||||||
|
LoadWeapSound(nightVisionWearSoundPlayer);
|
||||||
|
LoadWeapSound(nightVisionRemoveSound);
|
||||||
|
LoadWeapSound(nightVisionRemoveSoundPlayer);
|
||||||
|
LoadWeapSound(altSwitchSound);
|
||||||
|
LoadWeapSound(altSwitchSoundPlayer);
|
||||||
|
LoadWeapSound(raiseSound);
|
||||||
|
LoadWeapSound(raiseSoundPlayer);
|
||||||
|
LoadWeapSound(firstRaiseSound);
|
||||||
|
LoadWeapSound(firstRaiseSoundPlayer);
|
||||||
|
LoadWeapSound(putawaySound);
|
||||||
|
LoadWeapSound(putawaySoundPlayer);
|
||||||
|
LoadWeapSound(scanSound);
|
||||||
|
|
||||||
|
if (asset->weapDef->bounceSound)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < 31; i++)
|
||||||
|
{
|
||||||
|
LoadWeapSound(bounceSound[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LoadWeapSound(projExplosionSound);
|
||||||
|
LoadWeapSound(projDudSound);
|
||||||
|
LoadWeapSound(projIgnitionSound);
|
||||||
|
LoadWeapSound(turretOverheatSound);
|
||||||
|
LoadWeapSound(turretBarrelSpinMaxSnd);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
LoadWeapSound(turretBarrelSpinUpSnd[i]);
|
||||||
|
LoadWeapSound(turretBarrelSpinDownSnd[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
LoadWeapSound(missileConeSoundAlias);
|
||||||
|
LoadWeapSound(missileConeSoundAliasAtBase);
|
||||||
|
}
|
||||||
|
|
||||||
void IWeapon::writeWeaponDef(Game::WeaponDef* def, Components::ZoneBuilder::Zone* builder, Utils::Stream* buffer)
|
void IWeapon::writeWeaponDef(Game::WeaponDef* def, Components::ZoneBuilder::Zone* builder, Utils::Stream* buffer)
|
||||||
{
|
{
|
||||||
@ -274,9 +347,9 @@ namespace Assets
|
|||||||
{
|
{
|
||||||
buffer->align(Utils::Stream::ALIGN_4);
|
buffer->align(Utils::Stream::ALIGN_4);
|
||||||
int* ptrs = buffer->dest<int>();
|
int* ptrs = buffer->dest<int>();
|
||||||
buffer->saveMax(37 * sizeof(Game::snd_alias_list_t*));
|
buffer->saveMax(31 * sizeof(Game::snd_alias_list_t*));
|
||||||
|
|
||||||
for (int i = 0; i < 37; i++)
|
for (int i = 0; i < 31; i++)
|
||||||
{
|
{
|
||||||
if (!def->bounceSound[i])
|
if (!def->bounceSound[i])
|
||||||
{
|
{
|
||||||
@ -433,14 +506,16 @@ namespace Assets
|
|||||||
|
|
||||||
if (def->projExplosionSound)
|
if (def->projExplosionSound)
|
||||||
{
|
{
|
||||||
buffer->saveMax(4);
|
buffer->align(Utils::Stream::ALIGN_4);
|
||||||
|
buffer->saveMax(sizeof(Game::snd_alias_list_t*));
|
||||||
buffer->saveString(def->projExplosionSound->aliasName);
|
buffer->saveString(def->projExplosionSound->aliasName);
|
||||||
Utils::Stream::ClearPointer(&dest->projExplosionSound);
|
Utils::Stream::ClearPointer(&dest->projExplosionSound);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (def->projDudSound)
|
if (def->projDudSound)
|
||||||
{
|
{
|
||||||
buffer->saveMax(4);
|
buffer->align(Utils::Stream::ALIGN_4);
|
||||||
|
buffer->saveMax(sizeof(Game::snd_alias_list_t*));
|
||||||
buffer->saveString(def->projDudSound->aliasName);
|
buffer->saveString(def->projDudSound->aliasName);
|
||||||
Utils::Stream::ClearPointer(&dest->projDudSound);
|
Utils::Stream::ClearPointer(&dest->projDudSound);
|
||||||
}
|
}
|
||||||
@ -476,7 +551,8 @@ namespace Assets
|
|||||||
|
|
||||||
if (def->projIgnitionSound)
|
if (def->projIgnitionSound)
|
||||||
{
|
{
|
||||||
buffer->saveMax(4);
|
buffer->align(Utils::Stream::ALIGN_4);
|
||||||
|
buffer->saveMax(sizeof(Game::snd_alias_list_t*));
|
||||||
buffer->saveString(def->projIgnitionSound->aliasName);
|
buffer->saveString(def->projIgnitionSound->aliasName);
|
||||||
Utils::Stream::ClearPointer(&dest->projIgnitionSound);
|
Utils::Stream::ClearPointer(&dest->projIgnitionSound);
|
||||||
}
|
}
|
||||||
@ -551,7 +627,8 @@ namespace Assets
|
|||||||
|
|
||||||
if (def->turretOverheatSound)
|
if (def->turretOverheatSound)
|
||||||
{
|
{
|
||||||
buffer->saveMax(4);
|
buffer->align(Utils::Stream::ALIGN_4);
|
||||||
|
buffer->saveMax(sizeof(Game::snd_alias_list_t*));
|
||||||
buffer->saveString(def->turretOverheatSound->aliasName);
|
buffer->saveString(def->turretOverheatSound->aliasName);
|
||||||
Utils::Stream::ClearPointer(&dest->turretOverheatSound);
|
Utils::Stream::ClearPointer(&dest->turretOverheatSound);
|
||||||
}
|
}
|
||||||
@ -569,7 +646,8 @@ namespace Assets
|
|||||||
|
|
||||||
if (def->turretBarrelSpinMaxSnd)
|
if (def->turretBarrelSpinMaxSnd)
|
||||||
{
|
{
|
||||||
buffer->saveMax(4);
|
buffer->align(Utils::Stream::ALIGN_4);
|
||||||
|
buffer->saveMax(sizeof(Game::snd_alias_list_t*));
|
||||||
buffer->saveString(def->turretBarrelSpinMaxSnd->aliasName);
|
buffer->saveString(def->turretBarrelSpinMaxSnd->aliasName);
|
||||||
Utils::Stream::ClearPointer(&dest->turretBarrelSpinMaxSnd);
|
Utils::Stream::ClearPointer(&dest->turretBarrelSpinMaxSnd);
|
||||||
}
|
}
|
||||||
@ -577,7 +655,8 @@ namespace Assets
|
|||||||
for (int i = 0; i < 4; i++) {
|
for (int i = 0; i < 4; i++) {
|
||||||
if (!def->turretBarrelSpinUpSnd[i]) continue;
|
if (!def->turretBarrelSpinUpSnd[i]) continue;
|
||||||
|
|
||||||
buffer->saveMax(4);
|
buffer->align(Utils::Stream::ALIGN_4);
|
||||||
|
buffer->saveMax(sizeof(Game::snd_alias_list_t*));
|
||||||
buffer->saveString(def->turretBarrelSpinUpSnd[i]->aliasName);
|
buffer->saveString(def->turretBarrelSpinUpSnd[i]->aliasName);
|
||||||
Utils::Stream::ClearPointer(&dest->turretBarrelSpinUpSnd[i]);
|
Utils::Stream::ClearPointer(&dest->turretBarrelSpinUpSnd[i]);
|
||||||
}
|
}
|
||||||
@ -585,21 +664,24 @@ namespace Assets
|
|||||||
for (int i = 0; i < 4; i++) {
|
for (int i = 0; i < 4; i++) {
|
||||||
if (!def->turretBarrelSpinDownSnd[i]) continue;
|
if (!def->turretBarrelSpinDownSnd[i]) continue;
|
||||||
|
|
||||||
buffer->saveMax(4);
|
buffer->align(Utils::Stream::ALIGN_4);
|
||||||
|
buffer->saveMax(sizeof(Game::snd_alias_list_t*));
|
||||||
buffer->saveString(def->turretBarrelSpinDownSnd[i]->aliasName);
|
buffer->saveString(def->turretBarrelSpinDownSnd[i]->aliasName);
|
||||||
Utils::Stream::ClearPointer(&dest->turretBarrelSpinDownSnd[i]);
|
Utils::Stream::ClearPointer(&dest->turretBarrelSpinDownSnd[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (def->missileConeSoundAlias)
|
if (def->missileConeSoundAlias)
|
||||||
{
|
{
|
||||||
buffer->saveMax(4);
|
buffer->align(Utils::Stream::ALIGN_4);
|
||||||
|
buffer->saveMax(sizeof(Game::snd_alias_list_t*));
|
||||||
buffer->saveString(def->missileConeSoundAlias->aliasName);
|
buffer->saveString(def->missileConeSoundAlias->aliasName);
|
||||||
Utils::Stream::ClearPointer(&dest->missileConeSoundAlias);
|
Utils::Stream::ClearPointer(&dest->missileConeSoundAlias);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (def->missileConeSoundAliasAtBase)
|
if (def->missileConeSoundAliasAtBase)
|
||||||
{
|
{
|
||||||
buffer->saveMax(4);
|
buffer->align(Utils::Stream::ALIGN_4);
|
||||||
|
buffer->saveMax(sizeof(Game::snd_alias_list_t*));
|
||||||
buffer->saveString(def->missileConeSoundAliasAtBase->aliasName);
|
buffer->saveString(def->missileConeSoundAliasAtBase->aliasName);
|
||||||
Utils::Stream::ClearPointer(&dest->missileConeSoundAliasAtBase);
|
Utils::Stream::ClearPointer(&dest->missileConeSoundAliasAtBase);
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#include "StdInclude.hpp"
|
#include "StdInclude.hpp"
|
||||||
|
|
||||||
#define IW4X_CLIPMAP_VERSION 1
|
#define IW4X_CLIPMAP_VERSION 2
|
||||||
|
|
||||||
namespace Assets
|
namespace Assets
|
||||||
{
|
{
|
||||||
@ -587,12 +587,12 @@ namespace Assets
|
|||||||
|
|
||||||
Game::clipMap_t* orgClipMap = nullptr;
|
Game::clipMap_t* orgClipMap = nullptr;
|
||||||
Game::DB_EnumXAssets(Game::XAssetType::ASSET_TYPE_CLIPMAP_MP, [](Game::XAssetHeader header, void* clipMap)
|
Game::DB_EnumXAssets(Game::XAssetType::ASSET_TYPE_CLIPMAP_MP, [](Game::XAssetHeader header, void* clipMap)
|
||||||
{
|
|
||||||
if (!*reinterpret_cast<void**>(clipMap))
|
|
||||||
{
|
{
|
||||||
*reinterpret_cast<Game::clipMap_t**>(clipMap) = header.clipMap;
|
if (!*reinterpret_cast<void**>(clipMap))
|
||||||
}
|
{
|
||||||
}, &orgClipMap, false);
|
*reinterpret_cast<Game::clipMap_t**>(clipMap) = header.clipMap;
|
||||||
|
}
|
||||||
|
}, &orgClipMap, false);
|
||||||
|
|
||||||
if (orgClipMap) std::memcpy(clipMap, orgClipMap, sizeof Game::clipMap_t);
|
if (orgClipMap) std::memcpy(clipMap, orgClipMap, sizeof Game::clipMap_t);
|
||||||
|
|
||||||
@ -605,7 +605,7 @@ namespace Assets
|
|||||||
}
|
}
|
||||||
|
|
||||||
int version = reader.read<int>();
|
int version = reader.read<int>();
|
||||||
if (version != IW4X_CLIPMAP_VERSION)
|
if (version > IW4X_CLIPMAP_VERSION)
|
||||||
{
|
{
|
||||||
Components::Logger::Error(0, "Reading clipmap '%s' failed, expected version is %d, but it was %d!", name.data(), IW4X_CLIPMAP_VERSION, version);
|
Components::Logger::Error(0, "Reading clipmap '%s' failed, expected version is %d, but it was %d!", name.data(), IW4X_CLIPMAP_VERSION, version);
|
||||||
}
|
}
|
||||||
@ -881,33 +881,38 @@ namespace Assets
|
|||||||
clipMap->smodelNodeCount = reader.read<unsigned short>();
|
clipMap->smodelNodeCount = reader.read<unsigned short>();
|
||||||
clipMap->smodelNodes = reader.readArray<Game::SModelAabbNode>(clipMap->smodelNodeCount);
|
clipMap->smodelNodes = reader.readArray<Game::SModelAabbNode>(clipMap->smodelNodeCount);
|
||||||
|
|
||||||
clipMap->checksum = reader.read<int>();
|
|
||||||
|
|
||||||
clipMap->mapEnts = Components::AssetHandler::FindAssetForZone(Game::XAssetType::ASSET_TYPE_MAP_ENTS, Utils::String::VA("maps/mp/%s.d3dbsp", name.data()), builder).mapEnts;
|
clipMap->mapEnts = Components::AssetHandler::FindAssetForZone(Game::XAssetType::ASSET_TYPE_MAP_ENTS, Utils::String::VA("maps/mp/%s.d3dbsp", name.data()), builder).mapEnts;
|
||||||
|
|
||||||
// add triggers to mapEnts
|
// add triggers to mapEnts
|
||||||
/*
|
if (version >= 2) {
|
||||||
std::list<Game::TriggerSlab> slabs;
|
if (clipMap->numSubModels > 0) {
|
||||||
std::list<Game::TriggerHull> hulls;
|
clipMap->mapEnts->trigger.count = clipMap->numSubModels;
|
||||||
std::list<Game::TriggerModel> models;
|
clipMap->mapEnts->trigger.hullCount = clipMap->numSubModels;
|
||||||
|
|
||||||
for (int i = 0; i < clipMap->numCModels; ++i)
|
Game::TriggerHull* hulls = builder->getAllocator()->allocateArray<Game::TriggerHull>(clipMap->mapEnts->trigger.hullCount);
|
||||||
{
|
Game::TriggerModel* models = builder->getAllocator()->allocateArray<Game::TriggerModel>(clipMap->mapEnts->trigger.count);
|
||||||
Game::cLeafBrushNode_t* node = &clipMap->cLeafBrushNodes[clipMap->cModels[i].leaf.leafBrushNode];
|
|
||||||
if (!node->leafBrushCount) continue; // skip empty brushes
|
|
||||||
|
|
||||||
int baseHull = hulls.size();
|
for (unsigned int i = 0; i < clipMap->numSubModels; ++i)
|
||||||
for (int j = 0; j < node->leafBrushCount; ++j)
|
|
||||||
{
|
|
||||||
Game::cbrush_t* brush = &clipMap->cBrushes[node->data.leaf.brushes[j]];
|
|
||||||
int baseSlab = slabs.size();
|
|
||||||
for (int k = 0; k < brush->numsides; ++k)
|
|
||||||
{
|
{
|
||||||
Game::TriggerSlab curSlab;
|
models[i] = reader.read<Game::TriggerModel>();
|
||||||
|
hulls[i] = reader.read<Game::TriggerHull>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t slabCount = reader.read<size_t>();
|
||||||
|
clipMap->mapEnts->trigger.slabCount = slabCount;
|
||||||
|
Game::TriggerSlab* slabs = builder->getAllocator()->allocateArray<Game::TriggerSlab>(clipMap->mapEnts->trigger.slabCount);
|
||||||
|
for (unsigned int i = 0; i < clipMap->mapEnts->trigger.slabCount; i++) {
|
||||||
|
slabs[i] = reader.read<Game::TriggerSlab>();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
clipMap->mapEnts->trigger.models = &models[0];
|
||||||
|
clipMap->mapEnts->trigger.hulls = &hulls[0];
|
||||||
|
clipMap->mapEnts->trigger.slabs = &slabs[0];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
clipMap->checksum = reader.read<int>();
|
||||||
|
|
||||||
// This mustn't be null and has to have at least 1 'valid' entry.
|
// This mustn't be null and has to have at least 1 'valid' entry.
|
||||||
if (!clipMap->smodelNodeCount || !clipMap->smodelNodes)
|
if (!clipMap->smodelNodeCount || !clipMap->smodelNodes)
|
||||||
|
@ -4,10 +4,10 @@ namespace Assets
|
|||||||
{
|
{
|
||||||
void Isnd_alias_list_t::load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder)
|
void Isnd_alias_list_t::load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder)
|
||||||
{
|
{
|
||||||
Components::FileSystem::File aliasFile(Utils::String::VA("sounds/%s", name.data()));
|
Components::FileSystem::File aliasFile(Utils::String::VA("sounds/%s", name.c_str()));
|
||||||
if (!aliasFile.exists())
|
if (!aliasFile.exists())
|
||||||
{
|
{
|
||||||
header->sound = Components::AssetHandler::FindOriginalAsset(this->getType(), name.data()).sound;
|
header->sound = Components::AssetHandler::FindOriginalAsset(this->getType(), name.c_str()).sound;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -18,134 +18,330 @@ namespace Assets
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
aliasList->head = builder->getAllocator()->allocate<Game::snd_alias_t>();
|
std::string errors;
|
||||||
|
json11::Json infoData = json11::Json::parse(aliasFile.getBuffer(), errors);
|
||||||
|
json11::Json aliasesContainer = infoData["head"];
|
||||||
|
|
||||||
|
auto aliases = aliasesContainer.array_items();
|
||||||
|
|
||||||
|
aliasList->count = aliases.size();
|
||||||
|
|
||||||
|
// Allocate
|
||||||
|
aliasList->head = builder->getAllocator()->allocateArray<Game::snd_alias_t>(aliasList->count);
|
||||||
if (!aliasList->head)
|
if (!aliasList->head)
|
||||||
{
|
{
|
||||||
Components::Logger::Print("Error allocating memory for sound alias structure!\n");
|
Components::Logger::Print("Error allocating memory for sound alias structure!\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
aliasList->head->soundFile = builder->getAllocator()->allocate<Game::SoundFile>();
|
|
||||||
if (!aliasList->head->soundFile)
|
aliasList->aliasName = builder->getAllocator()->duplicateString(name.c_str());
|
||||||
|
|
||||||
|
for (size_t i = 0; i < aliasList->count; i++)
|
||||||
{
|
{
|
||||||
Components::Logger::Print("Error allocating memory for sound alias structure!\n");
|
json11::Json head = aliasesContainer[i];
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
aliasList->count = 1;
|
if (!infoData.is_object())
|
||||||
|
{
|
||||||
|
Components::Logger::Error("Failed to load sound %s!", name.c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
std::string errors;
|
aliasList->head->soundFile = builder->getAllocator()->allocate<Game::SoundFile>();
|
||||||
json11::Json infoData = json11::Json::parse(aliasFile.getBuffer(), errors);
|
if (!aliasList->head->soundFile)
|
||||||
|
{
|
||||||
|
Components::Logger::Print("Error allocating memory for sound alias structure!\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!infoData.is_object())
|
Game::snd_alias_t* alias = aliasList->head;
|
||||||
{
|
|
||||||
Components::Logger::Error("Failed to load sound %s!", name.data());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Game::snd_alias_t* alias = aliasList->head;
|
// try and parse everything and if it fails then fail for the whole file
|
||||||
|
auto type = head["type"];
|
||||||
|
auto subtitle = head["subtitle"];
|
||||||
|
auto secondaryAliasName = head["secondaryAliasName"];
|
||||||
|
auto chainAliasName = head["chainAliasName"];
|
||||||
|
auto soundFile = head["soundFile"];
|
||||||
|
auto sequence = head["sequence"];
|
||||||
|
auto volMin = head["volMin"];
|
||||||
|
auto volMax = head["volMax"];
|
||||||
|
auto pitchMin = head["pitchMin"];
|
||||||
|
auto pitchMax = head["pitchMax"];
|
||||||
|
auto distMin = head["distMin"];
|
||||||
|
auto distMax = head["distMax"];
|
||||||
|
auto flags = head["flags"];
|
||||||
|
auto slavePercentage = head["slavePercentage"];
|
||||||
|
auto probability = head["probability"];
|
||||||
|
auto lfePercentage = head["lfePercentage"];
|
||||||
|
auto centerPercentage = head["centerPercentage"];
|
||||||
|
auto startDelay = head["startDelay"];
|
||||||
|
auto volumeFalloffCurve = head["volumeFalloffCurve"];
|
||||||
|
auto envelopMin = head["envelopMin"];
|
||||||
|
auto envelopMax = head["envelopMax"];
|
||||||
|
auto envelopPercentage = head["envelopPercentage"];
|
||||||
|
auto speakerMap = head["speakerMap"];
|
||||||
|
auto aliasName = head["aliasName"];
|
||||||
|
|
||||||
// try and parse everything and if it fails then fail for the whole file
|
// Fix casing
|
||||||
auto type = infoData["type"];
|
if (soundFile.is_null())
|
||||||
auto subtitle = infoData["subtitle"];
|
{
|
||||||
auto secondaryAliasName = infoData["secondaryAliasName"];
|
soundFile = head["soundfile"];
|
||||||
auto chainAliasName = infoData["chainAliasName"];
|
|
||||||
auto soundFile = infoData["soundFile"];
|
|
||||||
auto sequence = infoData["sequence"];
|
|
||||||
auto volMin = infoData["volMin"];
|
|
||||||
auto volMax = infoData["volMax"];
|
|
||||||
auto pitchMin = infoData["pitchMin"];
|
|
||||||
auto pitchMax = infoData["pitchMax"];
|
|
||||||
auto distMin = infoData["distMin"];
|
|
||||||
auto distMax = infoData["distMax"];
|
|
||||||
auto flags = infoData["flags"];
|
|
||||||
auto slavePercentage = infoData["slavePercentage"];
|
|
||||||
auto probability = infoData["probability"];
|
|
||||||
auto lfePercentage = infoData["lfePercentage"];
|
|
||||||
auto centerPercentage = infoData["centerPercentage"];
|
|
||||||
auto startDelay = infoData["startDelay"];
|
|
||||||
auto volumeFalloffCurve = infoData["volumeFalloffCurve"];
|
|
||||||
auto envelopMin = infoData["envelopMin"];
|
|
||||||
auto envelopMax = infoData["envelopMax"];
|
|
||||||
auto envelopPercentage = infoData["envelopPercentage"];
|
|
||||||
auto speakerMap = infoData["speakerMap"];
|
|
||||||
|
|
||||||
if (type.is_null() || soundFile.is_null())
|
Components::Logger::Print("Fixed casing on %s\n", name.c_str());
|
||||||
{
|
}
|
||||||
Components::Logger::Error("Failed to parse sound %s! Each alias must have at least a type and a soundFile", name.data());
|
|
||||||
return;
|
if (type.is_null() || soundFile.is_null())
|
||||||
}
|
{
|
||||||
|
Components::Logger::Print("Type is %s\n", type.dump().c_str());
|
||||||
|
Components::Logger::Print("SoundFile is %s\n", soundFile.dump().c_str());
|
||||||
|
Components::Logger::Error("Failed to parse sound %s! Each alias must have at least a type and a soundFile\n", name.c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
#define CHECK(x, type) (x.is_##type##() || x.is_null())
|
#define CHECK(x, type) (x.is_##type##() || x.is_null())
|
||||||
|
|
||||||
// TODO: actually support all of those properties
|
// TODO: actually support all of those properties
|
||||||
if (CHECK(type, string) && CHECK(subtitle, string) && CHECK(secondaryAliasName, string) && CHECK(chainAliasName, string) &&
|
if (!CHECK(type, number))
|
||||||
CHECK(soundFile, string) && CHECK(sequence, number) && CHECK(volMin, number) && CHECK(volMax, number) && CHECK(pitchMin, number) &&
|
|
||||||
CHECK(pitchMax, number) && CHECK(distMin, number) && CHECK(distMax, number) && CHECK(flags, number) && CHECK(slavePercentage, number) &&
|
|
||||||
CHECK(probability, number) && CHECK(lfePercentage, number) && CHECK(centerPercentage, number) && CHECK(startDelay, number) &&
|
|
||||||
CHECK(volumeFalloffCurve, string) && CHECK(envelopMin, number) && CHECK(envelopMax, number) && CHECK(envelopPercentage, number) &&
|
|
||||||
CHECK(speakerMap, string))
|
|
||||||
{
|
|
||||||
|
|
||||||
alias->soundFile->exists = true;
|
|
||||||
|
|
||||||
if (subtitle.is_string())
|
|
||||||
{
|
{
|
||||||
alias->subtitle = subtitle.string_value().data();
|
Components::Logger::Print("%s is not number but %d (%s)\n", "type", type.type(), type.dump().c_str());
|
||||||
}
|
|
||||||
if (secondaryAliasName.is_string())
|
|
||||||
{
|
|
||||||
alias->secondaryAliasName = secondaryAliasName.string_value().data();
|
|
||||||
}
|
|
||||||
if (chainAliasName.is_string())
|
|
||||||
{
|
|
||||||
alias->chainAliasName = chainAliasName.string_value().data();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
alias->sequence = sequence.int_value();
|
if (!CHECK(subtitle, string))
|
||||||
alias->volMin = float(volMin.number_value());
|
|
||||||
alias->volMax = float(volMax.number_value());
|
|
||||||
alias->pitchMin = float(pitchMin.number_value());
|
|
||||||
alias->pitchMax = float(pitchMax.number_value());
|
|
||||||
alias->distMin = float(distMin.number_value());
|
|
||||||
alias->distMax = float(distMax.number_value());
|
|
||||||
alias->flags = flags.int_value();
|
|
||||||
alias->___u15.slavePercentage = float(slavePercentage.number_value());
|
|
||||||
alias->probability = float(probability.number_value());
|
|
||||||
alias->lfePercentage = float(lfePercentage.number_value());
|
|
||||||
alias->centerPercentage = float(centerPercentage.number_value());
|
|
||||||
alias->startDelay = startDelay.int_value();
|
|
||||||
alias->envelopMin = float(envelopMin.number_value());
|
|
||||||
alias->envelopMax = float(envelopMax.number_value());
|
|
||||||
alias->envelopPercentage = float(envelopPercentage.number_value());
|
|
||||||
|
|
||||||
if (volumeFalloffCurve.is_string())
|
|
||||||
{
|
{
|
||||||
alias->volumeFalloffCurve = Components::AssetHandler::FindAssetForZone(Game::XAssetType::ASSET_TYPE_SOUND_CURVE, volumeFalloffCurve.string_value(), builder).sndCurve;
|
Components::Logger::Print("%s is not string but %d (%s)\n", "subtitle", subtitle.type(), subtitle.dump().c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type.string_value() == "loaded"s)
|
if (!CHECK(aliasName, string))
|
||||||
{
|
{
|
||||||
alias->soundFile->type = Game::SAT_LOADED;
|
Components::Logger::Print("%s is not string but %d (%s)\n", "aliasName", aliasName.type(), aliasName.dump().c_str());
|
||||||
alias->soundFile->u.loadSnd = Components::AssetHandler::FindAssetForZone(Game::XAssetType::ASSET_TYPE_LOADED_SOUND, soundFile.string_value(), builder).loadSnd;
|
|
||||||
}
|
}
|
||||||
else if (type.string_value() == "streamed"s)
|
|
||||||
|
if (!CHECK(secondaryAliasName, string))
|
||||||
{
|
{
|
||||||
alias->soundFile->type = Game::SAT_STREAMED;
|
Components::Logger::Print("%s is not string but %d (%s)\n", "secondaryAliasName", secondaryAliasName.type(), secondaryAliasName.dump().c_str());
|
||||||
std::string streamedFile = soundFile.string_value();
|
}
|
||||||
int split = streamedFile.find_last_of('/');
|
|
||||||
alias->soundFile->u.streamSnd.filename.info.raw.dir = builder->getAllocator()->duplicateString(streamedFile.substr(0, split).c_str());
|
if (!CHECK(chainAliasName, string))
|
||||||
alias->soundFile->u.streamSnd.filename.info.raw.name = builder->getAllocator()->duplicateString(streamedFile.substr(split).c_str());
|
{
|
||||||
|
Components::Logger::Print("%s is not string but %d (%s)\n", "chainAliasName", chainAliasName.type(), chainAliasName.dump().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!CHECK(soundFile, string))
|
||||||
|
{
|
||||||
|
Components::Logger::Print("%s is not string but %d (%s)\n", "soundFile", soundFile.type(), soundFile.dump().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!CHECK(sequence, number))
|
||||||
|
{
|
||||||
|
Components::Logger::Print("%s is not number but %d (%s)\n", "sequence", sequence.type(), sequence.dump().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!CHECK(volMin, number))
|
||||||
|
{
|
||||||
|
Components::Logger::Print("%s is not number but %d (%s)\n", "volMin", volMin.type(), volMin.dump().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!CHECK(volMax, number))
|
||||||
|
{
|
||||||
|
Components::Logger::Print("%s is not number but %d (%s)\n", "volMax", volMax.type(), volMax.dump().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!CHECK(pitchMin, number))
|
||||||
|
{
|
||||||
|
Components::Logger::Print("%s is not number but %d (%s)\n", "pitchMin", pitchMin.type(), pitchMin.dump().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!CHECK(pitchMax, number))
|
||||||
|
{
|
||||||
|
Components::Logger::Print("%s is not number but %d (%s)\n", "pitchMax", pitchMax.type(), pitchMax.dump().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!CHECK(probability, number))
|
||||||
|
{
|
||||||
|
Components::Logger::Print("%s is not number but %d (%s)\n", "probability", probability.type(), probability.dump().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!CHECK(lfePercentage, number))
|
||||||
|
{
|
||||||
|
Components::Logger::Print("%s is not number but %d (%s)\n", "lfePercentage", lfePercentage.type(), lfePercentage.dump().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!CHECK(centerPercentage, number))
|
||||||
|
{
|
||||||
|
Components::Logger::Print("%s is not number but %d (%s)\n", "centerPercentage", centerPercentage.type(), centerPercentage.dump().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!CHECK(startDelay, number))
|
||||||
|
{
|
||||||
|
Components::Logger::Print("%s is not number but %d (%s)\n", "startDelay", startDelay.type(), startDelay.dump().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!CHECK(volumeFalloffCurve, string))
|
||||||
|
{
|
||||||
|
Components::Logger::Print("%s is not string but %d (%s)\n", "volumeFalloffCurve", volumeFalloffCurve.type(), volumeFalloffCurve.dump().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!CHECK(envelopMin, number))
|
||||||
|
{
|
||||||
|
Components::Logger::Print("%s is not number but %d (%s)\n", "envelopMin", envelopMin.type(), envelopMin.dump().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!CHECK(envelopMax, number))
|
||||||
|
{
|
||||||
|
Components::Logger::Print("%s is not number but %d (%s)\n", "envelopMax", envelopMax.type(), envelopMax.dump().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!CHECK(envelopPercentage, number))
|
||||||
|
{
|
||||||
|
Components::Logger::Print("%s is not number but %d (%s)\n", "envelopPercentage", envelopPercentage.type(), envelopPercentage.dump().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!CHECK(speakerMap, object))
|
||||||
|
{
|
||||||
|
Components::Logger::Print("%s is not object but %d (%s)\n", "speakerMap", speakerMap.type(), speakerMap.dump().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (CHECK(type, number) && CHECK(aliasName, string) && CHECK(subtitle, string) && CHECK(secondaryAliasName, string) && CHECK(chainAliasName, string) &&
|
||||||
|
CHECK(soundFile, string) && CHECK(sequence, number) && CHECK(volMin, number) && CHECK(volMax, number) && CHECK(pitchMin, number) &&
|
||||||
|
CHECK(pitchMax, number) && CHECK(distMin, number) && CHECK(distMax, number) && CHECK(flags, number) && CHECK(slavePercentage, number) &&
|
||||||
|
CHECK(probability, number) && CHECK(lfePercentage, number) && CHECK(centerPercentage, number) && CHECK(startDelay, number) &&
|
||||||
|
CHECK(volumeFalloffCurve, string) && CHECK(envelopMin, number) && CHECK(envelopMax, number) && CHECK(envelopPercentage, number) &&
|
||||||
|
CHECK(speakerMap, object))
|
||||||
|
{
|
||||||
|
|
||||||
|
alias->soundFile->exists = true;
|
||||||
|
alias->aliasName = builder->getAllocator()->duplicateString(aliasName.string_value().c_str());
|
||||||
|
|
||||||
|
if (subtitle.is_string())
|
||||||
|
{
|
||||||
|
alias->subtitle = builder->getAllocator()->duplicateString(subtitle.string_value().c_str());
|
||||||
|
}
|
||||||
|
if (secondaryAliasName.is_string())
|
||||||
|
{
|
||||||
|
alias->secondaryAliasName = builder->getAllocator()->duplicateString(secondaryAliasName.string_value().c_str());
|
||||||
|
}
|
||||||
|
if (chainAliasName.is_string())
|
||||||
|
{
|
||||||
|
alias->chainAliasName = builder->getAllocator()->duplicateString(chainAliasName.string_value().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
alias->sequence = sequence.int_value();
|
||||||
|
alias->volMin = float(volMin.number_value());
|
||||||
|
alias->volMax = float(volMax.number_value());
|
||||||
|
alias->pitchMin = float(pitchMin.number_value());
|
||||||
|
alias->pitchMax = float(pitchMax.number_value());
|
||||||
|
alias->distMin = float(distMin.number_value());
|
||||||
|
alias->distMax = float(distMax.number_value());
|
||||||
|
alias->flags = flags.int_value();
|
||||||
|
alias->___u15.slavePercentage = float(slavePercentage.number_value());
|
||||||
|
alias->probability = float(probability.number_value());
|
||||||
|
alias->lfePercentage = float(lfePercentage.number_value());
|
||||||
|
alias->centerPercentage = float(centerPercentage.number_value());
|
||||||
|
alias->startDelay = startDelay.int_value();
|
||||||
|
alias->envelopMin = float(envelopMin.number_value());
|
||||||
|
alias->envelopMax = float(envelopMax.number_value());
|
||||||
|
alias->envelopPercentage = float(envelopPercentage.number_value());
|
||||||
|
|
||||||
|
// Speaker map object
|
||||||
|
if (!speakerMap.is_null())
|
||||||
|
{
|
||||||
|
alias->speakerMap = builder->getAllocator()->allocate<Game::SpeakerMap>();
|
||||||
|
if (!alias->speakerMap)
|
||||||
|
{
|
||||||
|
Components::Logger::Print("Error allocating memory for speakermap in sound alias%s!\n", alias->aliasName);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
alias->speakerMap->name = builder->getAllocator()->duplicateString(speakerMap["name"].string_value().c_str());
|
||||||
|
alias->speakerMap->isDefault = speakerMap["isDefault"].bool_value();
|
||||||
|
|
||||||
|
if (speakerMap["channelMaps"].is_array())
|
||||||
|
{
|
||||||
|
json11::Json::array channelMaps = speakerMap["channelMaps"].array_items();
|
||||||
|
|
||||||
|
assert(channelMaps.size() <= 4);
|
||||||
|
|
||||||
|
// channelMapIndex should never exceed 1
|
||||||
|
for (size_t channelMapIndex = 0; channelMapIndex < 2; channelMapIndex++)
|
||||||
|
{
|
||||||
|
// subChannelIndex should never exceed 1
|
||||||
|
for (size_t subChannelIndex = 0; subChannelIndex < 2; subChannelIndex++)
|
||||||
|
{
|
||||||
|
json11::Json channelMap = channelMaps[channelMapIndex * 2 + subChannelIndex]; // 0-3
|
||||||
|
|
||||||
|
auto speakers = channelMap["speakers"].array_items();
|
||||||
|
|
||||||
|
alias->speakerMap->channelMaps[channelMapIndex][subChannelIndex].speakerCount = speakers.size();
|
||||||
|
|
||||||
|
for (size_t speakerIndex = 0; speakerIndex < alias->speakerMap->channelMaps[channelMapIndex][subChannelIndex].speakerCount; speakerIndex++)
|
||||||
|
{
|
||||||
|
auto speaker = speakers[speakerIndex];
|
||||||
|
alias->speakerMap->channelMaps[channelMapIndex][subChannelIndex].speakers[speakerIndex].levels[0] = static_cast<float>(speaker["levels0"].number_value());
|
||||||
|
alias->speakerMap->channelMaps[channelMapIndex][subChannelIndex].speakers[speakerIndex].levels[1] = static_cast<float>(speaker["levels1"].number_value());
|
||||||
|
alias->speakerMap->channelMaps[channelMapIndex][subChannelIndex].speakers[speakerIndex].numLevels = static_cast<int>(speaker["numLevels"].number_value());
|
||||||
|
alias->speakerMap->channelMaps[channelMapIndex][subChannelIndex].speakers[speakerIndex].speaker = static_cast<int>(speaker["speaker"].number_value());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (volumeFalloffCurve.is_string())
|
||||||
|
{
|
||||||
|
std::string fallOffCurve = volumeFalloffCurve.string_value();
|
||||||
|
|
||||||
|
if (fallOffCurve.size() == 0)
|
||||||
|
{
|
||||||
|
fallOffCurve = "$default";
|
||||||
|
}
|
||||||
|
|
||||||
|
auto curve = Components::AssetHandler::FindAssetForZone(
|
||||||
|
Game::XAssetType::ASSET_TYPE_SOUND_CURVE,
|
||||||
|
fallOffCurve.c_str(),
|
||||||
|
builder
|
||||||
|
).sndCurve;
|
||||||
|
|
||||||
|
alias->volumeFalloffCurve = curve;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (static_cast<Game::snd_alias_type_t>(type.number_value()) == Game::snd_alias_type_t::SAT_LOADED) // Loaded
|
||||||
|
{
|
||||||
|
alias->soundFile->type = Game::SAT_LOADED;
|
||||||
|
alias->soundFile->u.loadSnd = Components::AssetHandler::FindAssetForZone(Game::XAssetType::ASSET_TYPE_LOADED_SOUND, soundFile.string_value().c_str(), builder).loadSnd;
|
||||||
|
}
|
||||||
|
else if (static_cast<Game::snd_alias_type_t>(type.number_value()) == Game::snd_alias_type_t::SAT_STREAMED) // Streamed
|
||||||
|
{
|
||||||
|
alias->soundFile->type = Game::SAT_STREAMED;
|
||||||
|
|
||||||
|
std::string streamedFile = soundFile.string_value();
|
||||||
|
std::string directory = ""s;
|
||||||
|
int split = streamedFile.find_last_of('/');
|
||||||
|
|
||||||
|
if (split >= 0)
|
||||||
|
{
|
||||||
|
directory = streamedFile.substr(0, split);
|
||||||
|
streamedFile = streamedFile.substr(split+1);
|
||||||
|
}
|
||||||
|
|
||||||
|
alias->soundFile->u.streamSnd.filename.info.raw.dir = builder->getAllocator()->duplicateString(directory.c_str());
|
||||||
|
alias->soundFile->u.streamSnd.filename.info.raw.name = builder->getAllocator()->duplicateString(streamedFile.c_str());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Components::Logger::Error("Failed to parse sound %s! Invalid sound type %s\n", name.c_str(), type.string_value().c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
aliasList->head[i] = *alias;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Components::Logger::Error("Failed to parse sound %s! Invalid sound type %s", name.data(), type.string_value().c_str());
|
Components::Logger::Error("Failed to parse sound %s!\n", name.c_str());
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
header->sound = aliasList;
|
||||||
Components::Logger::Error("Failed to parse sound %s!", name.data());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
#undef CHECK
|
#undef CHECK
|
||||||
|
|
||||||
@ -155,7 +351,7 @@ namespace Assets
|
|||||||
{
|
{
|
||||||
Game::snd_alias_list_t* asset = header.sound;
|
Game::snd_alias_list_t* asset = header.sound;
|
||||||
|
|
||||||
for (int i = 0; i < asset->count; ++i)
|
for (unsigned int i = 0; i < asset->count; ++i)
|
||||||
{
|
{
|
||||||
Game::snd_alias_t* alias = &asset->head[i];
|
Game::snd_alias_t* alias = &asset->head[i];
|
||||||
|
|
||||||
@ -166,7 +362,12 @@ namespace Assets
|
|||||||
|
|
||||||
if (alias->volumeFalloffCurve)
|
if (alias->volumeFalloffCurve)
|
||||||
{
|
{
|
||||||
builder->loadAsset(Game::XAssetType::ASSET_TYPE_SOUND_CURVE, alias->volumeFalloffCurve);
|
if (!builder->loadAsset(Game::XAssetType::ASSET_TYPE_SOUND_CURVE, alias->volumeFalloffCurve))
|
||||||
|
{
|
||||||
|
// (Should never happen, but just in case)
|
||||||
|
alias->volumeFalloffCurve->filename = "$default";
|
||||||
|
builder->loadAsset(Game::XAssetType::ASSET_TYPE_SOUND_CURVE, alias->volumeFalloffCurve);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -204,7 +405,7 @@ namespace Assets
|
|||||||
Game::snd_alias_t* destHead = buffer->dest<Game::snd_alias_t>();
|
Game::snd_alias_t* destHead = buffer->dest<Game::snd_alias_t>();
|
||||||
buffer->saveArray(asset->head, asset->count);
|
buffer->saveArray(asset->head, asset->count);
|
||||||
|
|
||||||
for (int i = 0; i < asset->count; ++i)
|
for (unsigned int i = 0; i < asset->count; ++i)
|
||||||
{
|
{
|
||||||
Game::snd_alias_t* destAlias = &destHead[i];
|
Game::snd_alias_t* destAlias = &destHead[i];
|
||||||
Game::snd_alias_t* alias = &asset->head[i];
|
Game::snd_alias_t* alias = &asset->head[i];
|
||||||
|
@ -740,6 +740,22 @@ namespace Components
|
|||||||
Utils::Hook::Call<void(Game::gentity_s*, int, int)>(0x408910)(ent, unk, unk2);
|
Utils::Hook::Call<void(Game::gentity_s*, int, int)>(0x408910)(ent, unk, unk2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Maps::SV_SetTriggerModelHook(Game::gentity_s* ent) {
|
||||||
|
|
||||||
|
// Use me for debugging
|
||||||
|
//std::string classname = Game::SL_ConvertToString(ent->script_classname);
|
||||||
|
//std::string targetname = Game::SL_ConvertToString(ent->targetname);
|
||||||
|
|
||||||
|
return Utils::Hook::Call<bool(Game::gentity_s*)>(0x5050C0)(ent);
|
||||||
|
}
|
||||||
|
|
||||||
|
int16 Maps::CM_TriggerModelBounds(int modelPointer, Game::Bounds* bounds) {
|
||||||
|
#ifdef DEBUG
|
||||||
|
Game::MapEnts* ents = *reinterpret_cast<Game::MapEnts**>(0x1AA651C); // Use me for debugging
|
||||||
|
#endif
|
||||||
|
return Utils::Hook::Call<int16(int, Game::Bounds*)>(0x4416C0)(modelPointer, bounds);
|
||||||
|
}
|
||||||
|
|
||||||
Maps::Maps()
|
Maps::Maps()
|
||||||
{
|
{
|
||||||
Dvar::OnInit([]()
|
Dvar::OnInit([]()
|
||||||
@ -779,6 +795,15 @@ 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();
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
// Check trigger models
|
||||||
|
Utils::Hook(0x5FC0F1, 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
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
//#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
|
||||||
|
@ -120,5 +120,7 @@ namespace Components
|
|||||||
static void SetSpecularStub1();
|
static void SetSpecularStub1();
|
||||||
static void SetSpecularStub2();
|
static void SetSpecularStub2();
|
||||||
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 int16 CM_TriggerModelBounds(int brushModelPointer, Game::Bounds* bounds);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -946,17 +946,12 @@ namespace Components
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Dvar::OnInit([]
|
|
||||||
{
|
|
||||||
Dvar::Register<bool>("r_drawAabbTrees", false, Game::DVAR_FLAG_USERCREATED, "Draw aabb trees");
|
|
||||||
});
|
|
||||||
|
|
||||||
Scheduler::OnFrame([]()
|
Scheduler::OnFrame([]()
|
||||||
{
|
{
|
||||||
if (!Game::CL_IsCgameInitialized() || !Dvar::Var("r_drawAabbTrees").get<bool>()) return;
|
if (!Game::CL_IsCgameInitialized() || !Dvar::Var("r_drawAabbTrees").get<bool>()) return;
|
||||||
|
|
||||||
float cyan[4] = { 0.0f, 0.5f, 0.5f, 1.0f };
|
float cyan[4] = { 0.0f, 0.5f, 0.5f, 1.0f };
|
||||||
float red[4] = { 1.0f, 0.0f, 0.0f, 1.0f };
|
float red[4] = { 1.0f, 0.0f, 0.0f, 1.0f };
|
||||||
|
|
||||||
Game::clipMap_t* clipMap = *reinterpret_cast<Game::clipMap_t**>(0x7998E0);
|
Game::clipMap_t* clipMap = *reinterpret_cast<Game::clipMap_t**>(0x7998E0);
|
||||||
//Game::GfxWorld* gameWorld = *reinterpret_cast<Game::GfxWorld**>(0x66DEE94);
|
//Game::GfxWorld* gameWorld = *reinterpret_cast<Game::GfxWorld**>(0x66DEE94);
|
||||||
@ -973,6 +968,181 @@ namespace Components
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Dvar::OnInit([]
|
||||||
|
{
|
||||||
|
Dvar::Register<bool>("r_drawSceneModelBoundingBoxes", false, Game::DVAR_FLAG_CHEAT, "Draw scene model bounding boxes");
|
||||||
|
Dvar::Register<bool>("r_drawSceneModelCollisions", false, Game::DVAR_FLAG_CHEAT, "Draw scene model collisions");
|
||||||
|
Dvar::Register<bool>("r_drawTriggers", false, Game::DVAR_FLAG_CHEAT, "Draw triggers");
|
||||||
|
Dvar::Register<bool>("r_drawModelNames", false, Game::DVAR_FLAG_CHEAT, "Draw all model names");
|
||||||
|
Dvar::Register<bool>("r_drawAabbTrees", false, Game::DVAR_FLAG_USERCREATED, "Draw aabb trees");
|
||||||
|
});
|
||||||
|
|
||||||
|
Scheduler::OnFrame([]()
|
||||||
|
{
|
||||||
|
if (!Game::CL_IsCgameInitialized() || !Dvar::Var("r_drawModelNames").get<bool>()) return;
|
||||||
|
|
||||||
|
float sceneModelsColor[4] = { 1.0f, 1.0f, 0.0f, 1.0f };
|
||||||
|
float dobjsColor[4] = { 0.0f, 1.0f, 1.0f, 1.0f };
|
||||||
|
float staticModelsColor[4] = { 1.0f, 0.0f, 1.0f, 1.0f };
|
||||||
|
|
||||||
|
auto mapName = Dvar::Var("mapname").get<const char*>();
|
||||||
|
auto* scene = Game::scene;
|
||||||
|
auto world = Game::DB_FindXAssetEntry(Game::XAssetType::ASSET_TYPE_GFXWORLD, Utils::String::VA("maps/mp/%s.d3dbsp", mapName))->asset.header.gfxWorld;
|
||||||
|
|
||||||
|
for (auto i = 0; i < scene->sceneModelCount; i++)
|
||||||
|
{
|
||||||
|
if (!scene->sceneModel[i].model)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Game::R_AddDebugString(sceneModelsColor, scene->sceneModel[i].placement.base.origin, 1.0, scene->sceneModel[i].model->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto i = 0; i < scene->sceneDObjCount; i++)
|
||||||
|
{
|
||||||
|
if (scene->sceneDObj[i].obj) {
|
||||||
|
for (int j = 0; j < scene->sceneDObj[i].obj->numModels; j++)
|
||||||
|
{
|
||||||
|
Game::R_AddDebugString(dobjsColor, scene->sceneDObj[i].placement.origin, 1.0, scene->sceneDObj[i].obj->models[j]->name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Static models
|
||||||
|
for (size_t i = 0; i < world->dpvs.smodelCount; i++)
|
||||||
|
{
|
||||||
|
auto staticModel = world->dpvs.smodelDrawInsts[i];
|
||||||
|
if (staticModel.model) {
|
||||||
|
Game::R_AddDebugString(staticModelsColor, staticModel.placement.origin, 1.0, staticModel.model->name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Scheduler::OnFrame([]()
|
||||||
|
{
|
||||||
|
if (!Game::CL_IsCgameInitialized() || !Dvar::Var("r_drawSceneModelBoundingBoxes").get<bool>()) return;
|
||||||
|
|
||||||
|
float red[4] = { 1.0f, 0.0f, 0.0f, 1.0f };
|
||||||
|
float blue[4] = { 0.0f, 0.0f, 1.0f, 1.0f };
|
||||||
|
|
||||||
|
auto* scene = Game::scene;
|
||||||
|
|
||||||
|
for(auto i = 0; i < scene->sceneModelCount; i++)
|
||||||
|
{
|
||||||
|
if(!scene->sceneModel[i].model)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
auto b = scene->sceneModel[i].model->bounds;
|
||||||
|
b.midPoint[0] += scene->sceneModel[i].placement.base.origin[0];
|
||||||
|
b.midPoint[1] += scene->sceneModel[i].placement.base.origin[1];
|
||||||
|
b.midPoint[2] += scene->sceneModel[i].placement.base.origin[2];
|
||||||
|
b.halfSize[0] *= scene->sceneModel[i].placement.scale;
|
||||||
|
b.halfSize[1] *= scene->sceneModel[i].placement.scale;
|
||||||
|
b.halfSize[2] *= scene->sceneModel[i].placement.scale;
|
||||||
|
Game::R_AddDebugBounds(red, &b, &scene->sceneModel[i].placement.base.quat);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(auto i = 0; i < scene->sceneDObjCount; i++)
|
||||||
|
{
|
||||||
|
scene->sceneDObj[i].cull.bounds.halfSize[0] = std::abs(scene->sceneDObj[i].cull.bounds.halfSize[0]);
|
||||||
|
scene->sceneDObj[i].cull.bounds.halfSize[1] = std::abs(scene->sceneDObj[i].cull.bounds.halfSize[1]);
|
||||||
|
scene->sceneDObj[i].cull.bounds.halfSize[2] = std::abs(scene->sceneDObj[i].cull.bounds.halfSize[2]);
|
||||||
|
|
||||||
|
if (scene->sceneDObj[i].cull.bounds.halfSize[0] < 0 ||
|
||||||
|
scene->sceneDObj[i].cull.bounds.halfSize[1] < 0 ||
|
||||||
|
scene->sceneDObj[i].cull.bounds.halfSize[2] < 0) {
|
||||||
|
|
||||||
|
Components::Logger::Print("WARNING: Negative half size for DOBJ %s, this will cause culling issues!", scene->sceneDObj[i].obj->models[0]->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
Game::R_AddDebugBounds(blue, &scene->sceneDObj[i].cull.bounds);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Scheduler::OnFrame([]()
|
||||||
|
{
|
||||||
|
if (!Game::CL_IsCgameInitialized()) return;
|
||||||
|
if (!Dvar::Var("r_drawSceneModelCollisions").get<bool>()) return;
|
||||||
|
|
||||||
|
float green[4] = { 0.0f, 1.0f, 0.0f, 1.0f };
|
||||||
|
|
||||||
|
auto* scene = Game::scene;
|
||||||
|
|
||||||
|
for (auto i = 0; i < scene->sceneModelCount; i++)
|
||||||
|
{
|
||||||
|
if (!scene->sceneModel[i].model)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (auto j = 0; j < scene->sceneModel[i].model->numCollSurfs; j++) {
|
||||||
|
auto b = scene->sceneModel[i].model->collSurfs[j].bounds;
|
||||||
|
b.midPoint[0] += scene->sceneModel[i].placement.base.origin[0];
|
||||||
|
b.midPoint[1] += scene->sceneModel[i].placement.base.origin[1];
|
||||||
|
b.midPoint[2] += scene->sceneModel[i].placement.base.origin[2];
|
||||||
|
b.halfSize[0] *= scene->sceneModel[i].placement.scale;
|
||||||
|
b.halfSize[1] *= scene->sceneModel[i].placement.scale;
|
||||||
|
b.halfSize[2] *= scene->sceneModel[i].placement.scale;
|
||||||
|
|
||||||
|
Game::R_AddDebugBounds(green, &b, &scene->sceneModel[i].placement.base.quat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Scheduler::OnFrame([]()
|
||||||
|
{
|
||||||
|
if (!Game::CL_IsCgameInitialized() || !Dvar::Var("r_drawTriggers").get<bool>()) return;
|
||||||
|
|
||||||
|
float hurt[4] = { 1.0f, 0.0f, 0.0f, 1.0f };
|
||||||
|
float hurtTouch[4] = { 0.75f, 0.0f, 0.0f, 1.0f };
|
||||||
|
float damage[4] = { 0.0f, 0.0f, 1.0f, 1.0f };
|
||||||
|
float once[4] = { 0.0f, 1.0f, 1.0f, 1.0f };
|
||||||
|
float multiple[4] = { 0.0f, 1.0f, 0.0f, 1.0f };
|
||||||
|
|
||||||
|
auto* entities = Game::g_entities;
|
||||||
|
for(auto i = 0u; i < 0x800; i++)
|
||||||
|
{
|
||||||
|
auto* ent = &entities[i];
|
||||||
|
|
||||||
|
if(ent->r.isInUse)
|
||||||
|
{
|
||||||
|
Game::Bounds b = ent->r.box;
|
||||||
|
b.midPoint[0] += ent->r.currentOrigin[0];
|
||||||
|
b.midPoint[1] += ent->r.currentOrigin[1];
|
||||||
|
b.midPoint[2] += ent->r.currentOrigin[2];
|
||||||
|
|
||||||
|
switch(ent->handler)
|
||||||
|
{
|
||||||
|
case Game::ENT_HANDLER_TRIGGER_HURT:
|
||||||
|
Game::R_AddDebugBounds(hurt, &b);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Game::ENT_HANDLER_TRIGGER_HURT_TOUCH:
|
||||||
|
Game::R_AddDebugBounds(hurtTouch, &b);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Game::ENT_HANDLER_TRIGGER_DAMAGE:
|
||||||
|
Game::R_AddDebugBounds(damage, &b);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Game::ENT_HANDLER_TRIGGER_MULTIPLE:
|
||||||
|
if(ent->spawnflags & 0x40)
|
||||||
|
Game::R_AddDebugBounds(once, &b);
|
||||||
|
else
|
||||||
|
Game::R_AddDebugBounds(multiple, &b);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
float rv = std::min((float)ent->handler, (float)5) / 5;
|
||||||
|
float gv = std::clamp((float)ent->handler-5, (float)0, (float)5) / 5;
|
||||||
|
float bv = std::clamp((float)ent->handler - 10, (float)0, (float)5) / 5;
|
||||||
|
|
||||||
|
float color[4] = { rv, gv, bv, 1.0f };
|
||||||
|
|
||||||
|
Game::R_AddDebugBounds(color, &b);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
// Dvars
|
// Dvars
|
||||||
Dvar::Register<bool>("ui_streamFriendly", false, Game::DVAR_FLAG_SAVED, "Stream friendly UI");
|
Dvar::Register<bool>("ui_streamFriendly", false, Game::DVAR_FLAG_SAVED, "Stream friendly UI");
|
||||||
|
@ -108,7 +108,7 @@ namespace Components
|
|||||||
|
|
||||||
void Renderer::R_TextureFromCodeError(const char* sampler, Game::GfxCmdBufState* state)
|
void Renderer::R_TextureFromCodeError(const char* sampler, Game::GfxCmdBufState* state)
|
||||||
{
|
{
|
||||||
Game::Com_Error(0, "Tried to use '%s' when it isn't valid for material '%s' and technique '%s'",
|
Game::Com_Error(0, "Tried to use sampler '%s' when it isn't valid for material '%s' and technique '%s'",
|
||||||
sampler, state->material->info.name, state->technique->name);
|
sampler, state->material->info.name, state->technique->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -411,7 +411,7 @@ namespace Components
|
|||||||
{
|
{
|
||||||
Logger::Error(5, "Entity: %i is not a client", gentity);
|
Logger::Error(5, "Entity: %i is not a client", gentity);
|
||||||
}
|
}
|
||||||
return &Game::svs_clients[gentity->number];
|
return &Game::svs_clients[gentity->s.number];
|
||||||
}
|
}
|
||||||
|
|
||||||
void Script::AddFunctions()
|
void Script::AddFunctions()
|
||||||
|
@ -44,7 +44,7 @@ namespace Components
|
|||||||
|
|
||||||
if (!found)
|
if (!found)
|
||||||
{
|
{
|
||||||
Logger::Error("Asset %s of type %s was loaded, but not written!", name.data(), Game::DB_GetXAssetTypeName(subAsset.type));
|
Logger::Print("Asset %s of type %s was loaded, but not written!", name.data(), Game::DB_GetXAssetTypeName(subAsset.type));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -222,8 +222,10 @@ namespace Components
|
|||||||
}
|
}
|
||||||
|
|
||||||
Game::XAssetHeader assetHeader = AssetHandler::FindAssetForZone(type, name, this, isSubAsset);
|
Game::XAssetHeader assetHeader = AssetHandler::FindAssetForZone(type, name, this, isSubAsset);
|
||||||
|
|
||||||
if (!assetHeader.data)
|
if (!assetHeader.data)
|
||||||
{ Logger::Error("Error: Missing asset '%s' of type '%s'\n", name.data(), Game::DB_GetXAssetTypeName(type));
|
{
|
||||||
|
Logger::Error("Error: Missing asset '%s' of type '%s'\n", name.data(), Game::DB_GetXAssetTypeName(type));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -419,6 +419,8 @@ namespace Game
|
|||||||
|
|
||||||
clientstate_t* clcState = reinterpret_cast<clientstate_t*>(0xB2C540);
|
clientstate_t* clcState = reinterpret_cast<clientstate_t*>(0xB2C540);
|
||||||
|
|
||||||
|
GfxScene* scene = reinterpret_cast<GfxScene*>(0x6944914);
|
||||||
|
|
||||||
XAssetHeader ReallocateAssetPool(XAssetType type, unsigned int newSize)
|
XAssetHeader ReallocateAssetPool(XAssetType type, unsigned int newSize)
|
||||||
{
|
{
|
||||||
int elSize = DB_GetXAssetSizeHandlers[type]();
|
int elSize = DB_GetXAssetSizeHandlers[type]();
|
||||||
@ -728,6 +730,29 @@ namespace Game
|
|||||||
std::memmove(&solution[0], &res[0], sizeof(res));
|
std::memmove(&solution[0], &res[0], sizeof(res));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QuatRot(vec3_t* vec, const vec4_t* quat)
|
||||||
|
{
|
||||||
|
vec4_t q{ (*quat)[3],(*quat)[0],(*quat)[1],(*quat)[2] };
|
||||||
|
|
||||||
|
vec4_t res{ 0, (*vec)[0], (*vec)[1], (*vec)[2] };
|
||||||
|
vec4_t res2;
|
||||||
|
vec4_t quat_conj{ q[0], -q[1], -q[2], -q[3] };
|
||||||
|
QuatMultiply(&q, &res, &res2);
|
||||||
|
QuatMultiply(&res2, &quat_conj, &res);
|
||||||
|
|
||||||
|
(*vec)[0] = res[1];
|
||||||
|
(*vec)[1] = res[2];
|
||||||
|
(*vec)[2] = res[3];
|
||||||
|
}
|
||||||
|
|
||||||
|
void QuatMultiply(const vec4_t* q1, const vec4_t* q2, vec4_t* res)
|
||||||
|
{
|
||||||
|
(*res)[0] = (*q2)[0] * (*q1)[0] - (*q2)[1] * (*q1)[1] - (*q2)[2] * (*q1)[2] - (*q2)[3] * (*q1)[3];
|
||||||
|
(*res)[1] = (*q2)[0] * (*q1)[1] + (*q2)[1] * (*q1)[0] - (*q2)[2] * (*q1)[3] + (*q2)[3] * (*q1)[2];
|
||||||
|
(*res)[2] = (*q2)[0] * (*q1)[2] + (*q2)[1] * (*q1)[3] + (*q2)[2] * (*q1)[0] - (*q2)[3] * (*q1)[1];
|
||||||
|
(*res)[3] = (*q2)[0] * (*q1)[3] - (*q2)[1] * (*q1)[2] + (*q2)[2] * (*q1)[1] + (*q2)[3] * (*q1)[0];
|
||||||
|
}
|
||||||
|
|
||||||
void SortWorldSurfaces(GfxWorld* world)
|
void SortWorldSurfaces(GfxWorld* world)
|
||||||
{
|
{
|
||||||
DWORD* specular1 = reinterpret_cast<DWORD*>(0x69F105C);
|
DWORD* specular1 = reinterpret_cast<DWORD*>(0x69F105C);
|
||||||
@ -806,6 +831,73 @@ namespace Game
|
|||||||
Game::R_AddDebugLine(color, v4, v8);
|
Game::R_AddDebugLine(color, v4, v8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void R_AddDebugBounds(float* color, Bounds* b, const float(*quat)[4])
|
||||||
|
{
|
||||||
|
vec3_t v[8];
|
||||||
|
auto* center = b->midPoint;
|
||||||
|
auto* halfSize = b->halfSize;
|
||||||
|
|
||||||
|
v[0][0] = -halfSize[0];
|
||||||
|
v[0][1] = -halfSize[1];
|
||||||
|
v[0][2] = -halfSize[2];
|
||||||
|
|
||||||
|
v[1][0] = halfSize[0];
|
||||||
|
v[1][1] = -halfSize[1];
|
||||||
|
v[1][2] = -halfSize[2];
|
||||||
|
|
||||||
|
v[2][0] = -halfSize[0];
|
||||||
|
v[2][1] = halfSize[1];
|
||||||
|
v[2][2] = -halfSize[2];
|
||||||
|
|
||||||
|
v[3][0] = halfSize[0];
|
||||||
|
v[3][1] = halfSize[1];
|
||||||
|
v[3][2] = -halfSize[2];
|
||||||
|
|
||||||
|
v[4][0] = -halfSize[0];
|
||||||
|
v[4][1] = -halfSize[1];
|
||||||
|
v[4][2] = halfSize[2];
|
||||||
|
|
||||||
|
v[5][0] = halfSize[0];
|
||||||
|
v[5][1] = -halfSize[1];
|
||||||
|
v[5][2] = halfSize[2];
|
||||||
|
|
||||||
|
v[6][0] = -halfSize[0];
|
||||||
|
v[6][1] = halfSize[1];
|
||||||
|
v[6][2] = halfSize[2];
|
||||||
|
|
||||||
|
v[7][0] = halfSize[0];
|
||||||
|
v[7][1] = halfSize[1];
|
||||||
|
v[7][2] = halfSize[2];
|
||||||
|
|
||||||
|
for(auto& vec : v)
|
||||||
|
{
|
||||||
|
QuatRot(&vec, quat);
|
||||||
|
vec[0] += center[0];
|
||||||
|
vec[1] += center[1];
|
||||||
|
vec[2] += center[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
// bottom
|
||||||
|
Game::R_AddDebugLine(color, v[0], v[1]);
|
||||||
|
Game::R_AddDebugLine(color, v[1], v[3]);
|
||||||
|
Game::R_AddDebugLine(color, v[3], v[2]);
|
||||||
|
Game::R_AddDebugLine(color, v[2], v[0]);
|
||||||
|
|
||||||
|
// top
|
||||||
|
Game::R_AddDebugLine(color, v[4], v[5]);
|
||||||
|
Game::R_AddDebugLine(color, v[5], v[7]);
|
||||||
|
Game::R_AddDebugLine(color, v[7], v[6]);
|
||||||
|
Game::R_AddDebugLine(color, v[6], v[4]);
|
||||||
|
|
||||||
|
// verticals
|
||||||
|
Game::R_AddDebugLine(color, v[0], v[4]);
|
||||||
|
Game::R_AddDebugLine(color, v[1], v[5]);
|
||||||
|
Game::R_AddDebugLine(color, v[2], v[6]);
|
||||||
|
Game::R_AddDebugLine(color, v[3], v[7]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#pragma optimize("", off)
|
#pragma optimize("", off)
|
||||||
__declspec(naked) float UI_GetScoreboardLeft(void* /*a1*/)
|
__declspec(naked) float UI_GetScoreboardLeft(void* /*a1*/)
|
||||||
{
|
{
|
||||||
|
@ -858,6 +858,8 @@ namespace Game
|
|||||||
|
|
||||||
extern clientstate_t* clcState;
|
extern clientstate_t* clcState;
|
||||||
|
|
||||||
|
extern GfxScene* scene;
|
||||||
|
|
||||||
XAssetHeader ReallocateAssetPool(XAssetType type, unsigned int newSize);
|
XAssetHeader ReallocateAssetPool(XAssetType type, unsigned int newSize);
|
||||||
void Menu_FreeItemMemory(Game::itemDef_s* item);
|
void Menu_FreeItemMemory(Game::itemDef_s* item);
|
||||||
const char* TableLookup(StringTable* stringtable, int row, int column);
|
const char* TableLookup(StringTable* stringtable, int row, int column);
|
||||||
@ -906,9 +908,12 @@ namespace Game
|
|||||||
void Vec3Normalize(vec3_t& vec);
|
void Vec3Normalize(vec3_t& vec);
|
||||||
void Vec2UnpackTexCoords(const PackedTexCoords in, vec2_t* out);
|
void Vec2UnpackTexCoords(const PackedTexCoords in, vec2_t* out);
|
||||||
void MatrixVecMultiply(const float(&mulMat)[3][3], const vec3_t& mulVec, vec3_t& solution);
|
void MatrixVecMultiply(const float(&mulMat)[3][3], const vec3_t& mulVec, vec3_t& solution);
|
||||||
|
void QuatRot(vec3_t* vec, const vec4_t* quat);
|
||||||
|
void QuatMultiply(const vec4_t* q1, const vec4_t* q2, vec4_t* res);
|
||||||
|
|
||||||
void SortWorldSurfaces(GfxWorld* world);
|
void SortWorldSurfaces(GfxWorld* world);
|
||||||
void R_AddDebugLine(float* color, float* v1, float* v2);
|
void R_AddDebugLine(float* color, float* v1, float* v2);
|
||||||
void R_AddDebugString(float *color, float *pos, float scale, const char *str);
|
void R_AddDebugString(float *color, float *pos, float scale, const char *str);
|
||||||
void R_AddDebugBounds(float* color, Bounds* b);
|
void R_AddDebugBounds(float* color, Bounds* b);
|
||||||
|
void R_AddDebugBounds(float* color, Bounds* b, const float(*quat)[4]);
|
||||||
}
|
}
|
||||||
|
@ -906,7 +906,7 @@ namespace Game
|
|||||||
|
|
||||||
struct MSSChannelMap
|
struct MSSChannelMap
|
||||||
{
|
{
|
||||||
int speakerCount;
|
unsigned int speakerCount;
|
||||||
MSSSpeakerLevels speakers[6];
|
MSSSpeakerLevels speakers[6];
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -950,7 +950,7 @@ namespace Game
|
|||||||
{
|
{
|
||||||
const char *aliasName;
|
const char *aliasName;
|
||||||
snd_alias_t *head;
|
snd_alias_t *head;
|
||||||
int count;
|
unsigned int count;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct cStaticModel_s
|
struct cStaticModel_s
|
||||||
@ -4474,18 +4474,148 @@ namespace Game
|
|||||||
char pad3[724];
|
char pad3[724];
|
||||||
} gclient_t;
|
} gclient_t;
|
||||||
|
|
||||||
typedef struct gentity_s
|
struct LerpEntityState
|
||||||
|
{
|
||||||
|
char pad[0x70];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct clientLinkInfo_t
|
||||||
|
{
|
||||||
|
__int16 parentId;
|
||||||
|
char tagName;
|
||||||
|
char flags;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct entityState_s
|
||||||
{
|
{
|
||||||
int number;
|
int number;
|
||||||
unsigned char pad[308]; // 4
|
int eType;
|
||||||
float origin[3]; // 312
|
LerpEntityState lerp;
|
||||||
float angles[3]; // 324
|
int time2;
|
||||||
char pad2[8];
|
int otherEntityNum;
|
||||||
|
int attackerEntityNum;
|
||||||
|
int groundEntityNum;
|
||||||
|
int loopSound;
|
||||||
|
int surfType;
|
||||||
|
|
||||||
|
union
|
||||||
|
{
|
||||||
|
int brushModel;
|
||||||
|
int triggerModel;
|
||||||
|
int item;
|
||||||
|
int xmodel;
|
||||||
|
int primaryLight;
|
||||||
|
} index;
|
||||||
|
|
||||||
|
int clientNum;
|
||||||
|
int iHeadIcon;
|
||||||
|
int iHeadIconTeam;
|
||||||
|
int solid;
|
||||||
|
unsigned int eventParm;
|
||||||
|
int eventSequence;
|
||||||
|
int events[4];
|
||||||
|
unsigned int eventParms[4];
|
||||||
|
unsigned __int16 weapon;
|
||||||
|
int legsAnim;
|
||||||
|
int torsoAnim;
|
||||||
|
int un1;
|
||||||
|
int un2;
|
||||||
|
clientLinkInfo_t clientLinkInfo;
|
||||||
|
unsigned int partBits[6];
|
||||||
|
int clientMask[1];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct EntHandle
|
||||||
|
{
|
||||||
|
unsigned __int16 number;
|
||||||
|
unsigned __int16 infoIndex;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct entityShared_t
|
||||||
|
{
|
||||||
|
char isLinked;
|
||||||
|
char modelType;
|
||||||
|
char svFlags;
|
||||||
|
char isInUse;
|
||||||
|
Bounds box;
|
||||||
|
int contents;
|
||||||
|
Bounds absBox;
|
||||||
|
float currentOrigin[3];
|
||||||
|
float currentAngles[3];
|
||||||
|
EntHandle ownerNum;
|
||||||
|
int eventTime;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum EntHandler
|
||||||
|
{
|
||||||
|
ENT_HANDLER_NULL = 0x0,
|
||||||
|
ENT_HANDLER_TRIGGER_MULTIPLE = 0x1,
|
||||||
|
ENT_HANDLER_TRIGGER_HURT = 0x2,
|
||||||
|
ENT_HANDLER_TRIGGER_HURT_TOUCH = 0x3,
|
||||||
|
ENT_HANDLER_TRIGGER_DAMAGE = 0x4,
|
||||||
|
ENT_HANDLER_SCRIPT_MOVER = 0x5,
|
||||||
|
ENT_HANDLER_SCRIPT_MODEL = 0x6,
|
||||||
|
ENT_HANDLER_GRENADE = 0x7,
|
||||||
|
ENT_HANDLER_TIMED_OBJECT = 0x8,
|
||||||
|
ENT_HANDLER_ROCKET = 0x9,
|
||||||
|
ENT_HANDLER_CLIENT = 0xA,
|
||||||
|
ENT_HANDLER_CLIENT_SPECTATOR = 0xB,
|
||||||
|
ENT_HANDLER_CLIENT_DEAD = 0xC,
|
||||||
|
ENT_HANDLER_PLAYER_CLONE = 0xD,
|
||||||
|
ENT_HANDLER_TURRET_INIT = 0xE,
|
||||||
|
ENT_HANDLER_TURRET = 0xF,
|
||||||
|
ENT_HANDLER_DROPPED_ITEM = 0x10,
|
||||||
|
ENT_HANDLER_ITEM_INIT = 0x11,
|
||||||
|
ENT_HANDLER_ITEM = 0x12,
|
||||||
|
ENT_HANDLER_PRIMARY_LIGHT = 0x13,
|
||||||
|
ENT_HANDLER_PLAYER_BLOCK = 0x14,
|
||||||
|
ENT_HANDLER_VEHICLE = 0x15,
|
||||||
|
|
||||||
|
ENT_HANDLER_COUNT
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct gentity_s
|
||||||
|
{
|
||||||
|
entityState_s s;
|
||||||
|
entityShared_t r;
|
||||||
gclient_t* client; // 344
|
gclient_t* client; // 344
|
||||||
unsigned char pad3[28];
|
void /*Turret*/* turret;
|
||||||
|
void /*Vehicle*/* vehicle;
|
||||||
|
int physObjId;
|
||||||
|
unsigned __int16 model;
|
||||||
|
char physicsObject;
|
||||||
|
char takedamage;
|
||||||
|
char active;
|
||||||
|
char handler;
|
||||||
|
char team;
|
||||||
|
bool freeAfterEvent;
|
||||||
|
__int16 padding_short;
|
||||||
short classname;
|
short classname;
|
||||||
short pad4;
|
unsigned __int16 script_classname;
|
||||||
unsigned char pad5[248];
|
unsigned __int16 script_linkName;
|
||||||
|
unsigned __int16 target;
|
||||||
|
unsigned __int16 targetname;
|
||||||
|
unsigned int attachIgnoreCollision;
|
||||||
|
int spawnflags;
|
||||||
|
int flags;
|
||||||
|
int eventTime;
|
||||||
|
int clipmask;
|
||||||
|
int processedFrame;
|
||||||
|
EntHandle parent;
|
||||||
|
int nextthink;
|
||||||
|
int health;
|
||||||
|
int maxHealth;
|
||||||
|
int damage;
|
||||||
|
int count;
|
||||||
|
EntHandle missileTargetEnt;
|
||||||
|
EntHandle remoteControlledOwner;
|
||||||
|
gentity_s* tagChildren;
|
||||||
|
unsigned __int16 attachModelNames[19];
|
||||||
|
unsigned __int16 attachTagNames[19];
|
||||||
|
int useCount;
|
||||||
|
gentity_s* nextFree;
|
||||||
|
int birthTime;
|
||||||
|
char pad[100];
|
||||||
} gentity_t;
|
} gentity_t;
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
#pragma pack(push, 1)
|
||||||
@ -4829,6 +4959,310 @@ namespace Game
|
|||||||
GfxCmdBufState *state;
|
GfxCmdBufState *state;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct GfxDrawGroupSetupFields
|
||||||
|
{
|
||||||
|
unsigned __int16 materialSortedIndex : 15;
|
||||||
|
unsigned __int16 useHeroLighting : 1;
|
||||||
|
char sceneLightIndex;
|
||||||
|
char surfType;
|
||||||
|
};
|
||||||
|
|
||||||
|
union GfxDrawGroupSetup
|
||||||
|
{
|
||||||
|
GfxDrawGroupSetupFields fields;
|
||||||
|
unsigned int packed;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GfxMarkSurfLightingFields
|
||||||
|
{
|
||||||
|
char lmapIndex;
|
||||||
|
char reflectionProbeIndex;
|
||||||
|
unsigned __int16 modelIndex;
|
||||||
|
};
|
||||||
|
|
||||||
|
union GfxMarkSurfLighting
|
||||||
|
{
|
||||||
|
GfxMarkSurfLightingFields fields;
|
||||||
|
unsigned int packed;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GfxMarkSurf
|
||||||
|
{
|
||||||
|
GfxDrawGroupSetup drawGroup;
|
||||||
|
unsigned __int16* indices;
|
||||||
|
unsigned __int16 triCount;
|
||||||
|
char modelType;
|
||||||
|
char pad;
|
||||||
|
GfxMarkSurfLighting lighting;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GfxCodeSurf
|
||||||
|
{
|
||||||
|
GfxDrawGroupSetup drawGroup;
|
||||||
|
unsigned int triCount;
|
||||||
|
unsigned __int16* indices;
|
||||||
|
unsigned __int16 argOffset;
|
||||||
|
unsigned __int16 argCount;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct __declspec(align(4)) GfxGlassSurf
|
||||||
|
{
|
||||||
|
GfxDrawGroupSetup drawGroup;
|
||||||
|
char pad;
|
||||||
|
char reflectionProbeIndex;
|
||||||
|
unsigned __int16 triCount;
|
||||||
|
unsigned __int16* indices;
|
||||||
|
unsigned __int16 lightingHandle;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GfxCloudSurfFields
|
||||||
|
{
|
||||||
|
unsigned __int16 materialSortedIndex;
|
||||||
|
char cloudDataIndex;
|
||||||
|
char surfType;
|
||||||
|
};
|
||||||
|
|
||||||
|
union GfxCloudSurf
|
||||||
|
{
|
||||||
|
GfxCloudSurfFields fields;
|
||||||
|
unsigned int packed;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GfxSparkSurfFields
|
||||||
|
{
|
||||||
|
unsigned __int16 materialSortedIndex;
|
||||||
|
unsigned __int16 sparkDataIndex;
|
||||||
|
};
|
||||||
|
|
||||||
|
union GfxSparkSurf
|
||||||
|
{
|
||||||
|
GfxSparkSurfFields fields;
|
||||||
|
unsigned int packed;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GfxSceneDef
|
||||||
|
{
|
||||||
|
int time;
|
||||||
|
float floatTime;
|
||||||
|
float viewOffset[3];
|
||||||
|
GfxImage* sunShadowImage;
|
||||||
|
float sunShadowPixelAdjust[4];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GfxLight
|
||||||
|
{
|
||||||
|
char type;
|
||||||
|
char canUseShadowMap;
|
||||||
|
char unused[2];
|
||||||
|
float color[3];
|
||||||
|
float dir[3];
|
||||||
|
float origin[3];
|
||||||
|
float radius;
|
||||||
|
float cosHalfFovOuter;
|
||||||
|
float cosHalfFovInner;
|
||||||
|
int exponent;
|
||||||
|
unsigned int spotShadowIndex;
|
||||||
|
GfxLightDef* def;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GfxVisibleLight
|
||||||
|
{
|
||||||
|
char pad[0x2004];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GfxEntity
|
||||||
|
{
|
||||||
|
unsigned int renderFxFlags;
|
||||||
|
float materialTime;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GfxSkinnedXModelSurfs
|
||||||
|
{
|
||||||
|
void* firstSurf;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GfxSceneEntityCull
|
||||||
|
{
|
||||||
|
volatile unsigned int state;
|
||||||
|
Bounds bounds;
|
||||||
|
GfxSkinnedXModelSurfs skinnedSurfs;
|
||||||
|
};
|
||||||
|
|
||||||
|
union GfxSceneEntityInfo
|
||||||
|
{
|
||||||
|
void/*cpose_t*/* pose;
|
||||||
|
unsigned __int16* cachedLightingHandle;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DSkelPartBits
|
||||||
|
{
|
||||||
|
int anim[6];
|
||||||
|
int control[6];
|
||||||
|
int worldCtrl[6];
|
||||||
|
int skel[6];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DSkel
|
||||||
|
{
|
||||||
|
DSkelPartBits partBits;
|
||||||
|
int timeStamp;
|
||||||
|
/*DObjAnimMat*/void* mat;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DObj
|
||||||
|
{
|
||||||
|
/*XAnimTree_s*/ void* tree;
|
||||||
|
unsigned __int16 duplicateParts;
|
||||||
|
unsigned __int16 entnum;
|
||||||
|
char duplicatePartsSize;
|
||||||
|
char numModels;
|
||||||
|
char numBones;
|
||||||
|
char flags;
|
||||||
|
unsigned int ignoreCollision;
|
||||||
|
volatile int locked;
|
||||||
|
DSkel skel;
|
||||||
|
float radius;
|
||||||
|
unsigned int hidePartBits[6];
|
||||||
|
XModel** models;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GfxSceneEntity
|
||||||
|
{
|
||||||
|
float lightingOrigin[3];
|
||||||
|
GfxPlacement placement;
|
||||||
|
GfxSceneEntityCull cull;
|
||||||
|
char lods[32];
|
||||||
|
unsigned __int32 gfxEntIndex : 7;
|
||||||
|
unsigned __int32 entnum : 12;
|
||||||
|
unsigned __int32 renderFxFlags : 13;
|
||||||
|
DObj* obj;
|
||||||
|
GfxSceneEntityInfo info;
|
||||||
|
char reflectionProbeIndex;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GfxScaledPlacement
|
||||||
|
{
|
||||||
|
GfxPlacement base;
|
||||||
|
float scale;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GfxSceneModel
|
||||||
|
{
|
||||||
|
XModelDrawInfo info;
|
||||||
|
XModel* model;
|
||||||
|
DObj* obj;
|
||||||
|
GfxScaledPlacement placement;
|
||||||
|
unsigned __int32 gfxEntIndex : 7;
|
||||||
|
unsigned __int32 entnum : 12;
|
||||||
|
unsigned __int32 renderFxFlags : 13;
|
||||||
|
float radius;
|
||||||
|
unsigned __int16* cachedLightingHandle;
|
||||||
|
float lightingOrigin[3];
|
||||||
|
char reflectionProbeIndex;
|
||||||
|
char lod;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct __declspec(align(4)) GfxSceneBrush
|
||||||
|
{
|
||||||
|
BModelDrawInfo info;
|
||||||
|
unsigned __int16 entnum;
|
||||||
|
GfxBrushModel* bmodel;
|
||||||
|
GfxPlacement placement;
|
||||||
|
char reflectionProbeIndex;
|
||||||
|
};
|
||||||
|
|
||||||
|
union GfxSceneGlass
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
bool rendered;
|
||||||
|
char reflectionProbeIndex;
|
||||||
|
unsigned __int16 lightingHandle;
|
||||||
|
};
|
||||||
|
unsigned int packed;
|
||||||
|
};
|
||||||
|
|
||||||
|
union GfxEntCellRefInfo
|
||||||
|
{
|
||||||
|
float radius;
|
||||||
|
GfxBrushModel* bmodel;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GfxSceneDpvs
|
||||||
|
{
|
||||||
|
unsigned int localClientNum;
|
||||||
|
char* entVisData[7];
|
||||||
|
unsigned __int16* sceneXModelIndex;
|
||||||
|
unsigned __int16* sceneDObjIndex;
|
||||||
|
GfxEntCellRefInfo* entInfo[4];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct __declspec(align(64)) GfxScene
|
||||||
|
{
|
||||||
|
GfxCodeSurf codeEmissiveSurfs[2048];
|
||||||
|
GfxCodeSurf codeTransSurfs[640];
|
||||||
|
GfxMarkSurf markSurfs[1536];
|
||||||
|
GfxGlassSurf glassSurfs[768];
|
||||||
|
GfxCloudSurf cloudSurfs[256];
|
||||||
|
GfxDrawSurf drawSurfsDepthHack[32];
|
||||||
|
GfxDrawSurf drawSurfsLitOpaque[8192];
|
||||||
|
GfxDrawSurf drawSurfsLitTrans[2048];
|
||||||
|
GfxDrawSurf drawSurfsEmissive[8192];
|
||||||
|
GfxDrawSurf drawSurfsSunShadow0[4096];
|
||||||
|
GfxDrawSurf drawSurfsSunShadow1[8192];
|
||||||
|
GfxDrawSurf drawSurfsSpotShadow0[896];
|
||||||
|
GfxDrawSurf drawSurfsSpotShadow1[896];
|
||||||
|
GfxDrawSurf drawSurfsSpotShadow2[896];
|
||||||
|
GfxDrawSurf drawSurfsSpotShadow3[896];
|
||||||
|
unsigned int sceneLightIsUsed[32];
|
||||||
|
unsigned int cachedSceneLightIsUsed[4][32];
|
||||||
|
GfxSparkSurf sparkSurfs[64];
|
||||||
|
unsigned int drawSurfLimit[10];
|
||||||
|
volatile int drawSurfCount[10];
|
||||||
|
GfxDrawSurf* drawSurfs[10];
|
||||||
|
volatile int codeSurfUser[2];
|
||||||
|
volatile int markMeshGuard;
|
||||||
|
unsigned int codeEmissiveSurfCount;
|
||||||
|
unsigned int codeTransSurfCount;
|
||||||
|
unsigned int markSurfCount;
|
||||||
|
unsigned int glassSurfCount;
|
||||||
|
GfxSceneDef def;
|
||||||
|
unsigned int addedLightCount;
|
||||||
|
GfxLight addedLight[32];
|
||||||
|
bool isAddedLightCulled[32];
|
||||||
|
float dynamicSpotLightNearPlaneOffset;
|
||||||
|
float dynamicSpotLightLength;
|
||||||
|
GfxVisibleLight visLight[4];
|
||||||
|
GfxVisibleLight visLightShadow[1];
|
||||||
|
unsigned int* entOverflowedDrawBuf;
|
||||||
|
volatile int gfxEntCount;
|
||||||
|
GfxEntity gfxEnts[128];
|
||||||
|
int sceneDObjCount;
|
||||||
|
int preClientSceneDObjCount;
|
||||||
|
int sceneDObjCountAtMark;
|
||||||
|
GfxSceneEntity sceneDObj[520];
|
||||||
|
char sceneDObjVisData[7][512];
|
||||||
|
int sceneDObjMarkableViewmodelIndex;
|
||||||
|
unsigned int sceneDObjFirstViewmodelIndex;
|
||||||
|
unsigned int sceneDObjViewmodelCount;
|
||||||
|
volatile int sceneModelCount;
|
||||||
|
int sceneModelCountAtMark;
|
||||||
|
int sceneDObjModelCount;
|
||||||
|
GfxSceneModel sceneModel[1024];
|
||||||
|
char sceneModelVisData[7][1024];
|
||||||
|
volatile int sceneBrushCount;
|
||||||
|
int sceneBrushCountAtMark;
|
||||||
|
GfxSceneBrush sceneBrush[512];
|
||||||
|
char sceneBrushVisData[3][512];
|
||||||
|
GfxSceneGlass sceneGlass[1024];
|
||||||
|
unsigned int sceneDynModelCount;
|
||||||
|
unsigned int sceneDynBrushCount;
|
||||||
|
int gfxEntCountAtMark;
|
||||||
|
GfxSceneDpvs dpvs;
|
||||||
|
int updateSound;
|
||||||
|
int allowAddDObj;
|
||||||
|
};
|
||||||
|
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
|
||||||
#ifndef IDA
|
#ifndef IDA
|
||||||
|
@ -5,8 +5,8 @@
|
|||||||
|
|
||||||
#ifndef RC_INVOKED
|
#ifndef RC_INVOKED
|
||||||
|
|
||||||
#define _HAS_CXX17 1
|
//#define _HAS_CXX17 1
|
||||||
#define _HAS_CXX20 1
|
//#define _HAS_CXX20 1
|
||||||
#define VC_EXTRALEAN
|
#define VC_EXTRALEAN
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
#define _CRT_SECURE_NO_WARNINGS
|
#define _CRT_SECURE_NO_WARNINGS
|
||||||
@ -38,6 +38,7 @@
|
|||||||
#include <future>
|
#include <future>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
// Experimental C++17 features
|
// Experimental C++17 features
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
Loading…
Reference in New Issue
Block a user