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()
|
||||
|
||||
workspace "*"
|
||||
buildoptions {
|
||||
"/std:c++latest"
|
||||
}
|
||||
systemversion "latest"
|
||||
cppdialect "C++17"
|
||||
defines { "_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS" }
|
||||
|
||||
rule "ProtobufCompiler"
|
||||
|
@ -7,12 +7,13 @@ namespace Assets
|
||||
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 /*&& !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 /*&& !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)
|
||||
{
|
||||
|
||||
switch (elemType)
|
||||
{
|
||||
case Game::FX_ELEM_TYPE_MODEL:
|
||||
@ -34,10 +35,7 @@ namespace Assets
|
||||
if (visuals->soundName)
|
||||
{
|
||||
visuals->soundName = reader->readCString();
|
||||
visuals->soundName = "null";
|
||||
Components::Logger::Print("Unable to load sounds yet!\n");
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -4,7 +4,7 @@ namespace Assets
|
||||
{
|
||||
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())
|
||||
{
|
||||
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.samples = 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.bits = reader.read<short>();
|
||||
|
||||
|
@ -29,6 +29,33 @@ namespace Assets
|
||||
"_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()));
|
||||
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]) 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;
|
||||
};
|
||||
|
||||
|
||||
Game::DB_EnumXAssetEntries(Game::XAssetType::ASSET_TYPE_MATERIAL, [asset, techsetMatches](Game::XAssetEntry* entry)
|
||||
{
|
||||
if (!replacementFound)
|
||||
@ -209,8 +238,52 @@ namespace Assets
|
||||
|
||||
if (!replacementFound && asset->techniqueSet)
|
||||
{
|
||||
|
||||
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())
|
||||
|
@ -15,9 +15,9 @@ namespace Assets
|
||||
}
|
||||
}
|
||||
|
||||
void IWeapon::mark(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder)
|
||||
{
|
||||
Game::WeaponCompleteDef* asset = header.weapon;
|
||||
void IWeapon::mark(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder)
|
||||
{
|
||||
Game::WeaponCompleteDef* asset = header.weapon;
|
||||
|
||||
// convert all script strings
|
||||
if (asset->hideTags)
|
||||
@ -64,7 +64,7 @@ namespace Assets
|
||||
builder->addScriptString(asset->weapDef->notetrackRumbleMapValues[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// now load all sub-assets properly
|
||||
if (asset->killIcon) builder->loadAsset(Game::XAssetType::ASSET_TYPE_MATERIAL, asset->killIcon);
|
||||
@ -119,7 +119,80 @@ namespace Assets
|
||||
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->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)
|
||||
{
|
||||
@ -274,9 +347,9 @@ namespace Assets
|
||||
{
|
||||
buffer->align(Utils::Stream::ALIGN_4);
|
||||
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])
|
||||
{
|
||||
@ -433,14 +506,16 @@ namespace Assets
|
||||
|
||||
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);
|
||||
Utils::Stream::ClearPointer(&dest->projExplosionSound);
|
||||
}
|
||||
|
||||
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);
|
||||
Utils::Stream::ClearPointer(&dest->projDudSound);
|
||||
}
|
||||
@ -476,7 +551,8 @@ namespace Assets
|
||||
|
||||
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);
|
||||
Utils::Stream::ClearPointer(&dest->projIgnitionSound);
|
||||
}
|
||||
@ -551,7 +627,8 @@ namespace Assets
|
||||
|
||||
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);
|
||||
Utils::Stream::ClearPointer(&dest->turretOverheatSound);
|
||||
}
|
||||
@ -569,7 +646,8 @@ namespace Assets
|
||||
|
||||
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);
|
||||
Utils::Stream::ClearPointer(&dest->turretBarrelSpinMaxSnd);
|
||||
}
|
||||
@ -577,7 +655,8 @@ namespace Assets
|
||||
for (int i = 0; i < 4; i++) {
|
||||
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);
|
||||
Utils::Stream::ClearPointer(&dest->turretBarrelSpinUpSnd[i]);
|
||||
}
|
||||
@ -585,21 +664,24 @@ namespace Assets
|
||||
for (int i = 0; i < 4; i++) {
|
||||
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);
|
||||
Utils::Stream::ClearPointer(&dest->turretBarrelSpinDownSnd[i]);
|
||||
}
|
||||
|
||||
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);
|
||||
Utils::Stream::ClearPointer(&dest->missileConeSoundAlias);
|
||||
}
|
||||
|
||||
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);
|
||||
Utils::Stream::ClearPointer(&dest->missileConeSoundAliasAtBase);
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
#include "StdInclude.hpp"
|
||||
|
||||
#define IW4X_CLIPMAP_VERSION 1
|
||||
#define IW4X_CLIPMAP_VERSION 2
|
||||
|
||||
namespace Assets
|
||||
{
|
||||
@ -587,12 +587,12 @@ namespace Assets
|
||||
|
||||
Game::clipMap_t* orgClipMap = nullptr;
|
||||
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;
|
||||
}
|
||||
}, &orgClipMap, false);
|
||||
if (!*reinterpret_cast<void**>(clipMap))
|
||||
{
|
||||
*reinterpret_cast<Game::clipMap_t**>(clipMap) = header.clipMap;
|
||||
}
|
||||
}, &orgClipMap, false);
|
||||
|
||||
if (orgClipMap) std::memcpy(clipMap, orgClipMap, sizeof Game::clipMap_t);
|
||||
|
||||
@ -605,7 +605,7 @@ namespace Assets
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
@ -881,33 +881,38 @@ namespace Assets
|
||||
clipMap->smodelNodeCount = reader.read<unsigned short>();
|
||||
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;
|
||||
|
||||
// add triggers to mapEnts
|
||||
/*
|
||||
std::list<Game::TriggerSlab> slabs;
|
||||
std::list<Game::TriggerHull> hulls;
|
||||
std::list<Game::TriggerModel> models;
|
||||
if (version >= 2) {
|
||||
if (clipMap->numSubModels > 0) {
|
||||
clipMap->mapEnts->trigger.count = clipMap->numSubModels;
|
||||
clipMap->mapEnts->trigger.hullCount = clipMap->numSubModels;
|
||||
|
||||
for (int i = 0; i < clipMap->numCModels; ++i)
|
||||
{
|
||||
Game::cLeafBrushNode_t* node = &clipMap->cLeafBrushNodes[clipMap->cModels[i].leaf.leafBrushNode];
|
||||
if (!node->leafBrushCount) continue; // skip empty brushes
|
||||
Game::TriggerHull* hulls = builder->getAllocator()->allocateArray<Game::TriggerHull>(clipMap->mapEnts->trigger.hullCount);
|
||||
Game::TriggerModel* models = builder->getAllocator()->allocateArray<Game::TriggerModel>(clipMap->mapEnts->trigger.count);
|
||||
|
||||
int baseHull = hulls.size();
|
||||
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)
|
||||
for (unsigned int i = 0; i < clipMap->numSubModels; ++i)
|
||||
{
|
||||
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.
|
||||
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)
|
||||
{
|
||||
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())
|
||||
{
|
||||
header->sound = Components::AssetHandler::FindOriginalAsset(this->getType(), name.data()).sound;
|
||||
header->sound = Components::AssetHandler::FindOriginalAsset(this->getType(), name.c_str()).sound;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -18,134 +18,330 @@ namespace Assets
|
||||
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)
|
||||
{
|
||||
Components::Logger::Print("Error allocating memory for sound alias structure!\n");
|
||||
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");
|
||||
return;
|
||||
}
|
||||
json11::Json head = aliasesContainer[i];
|
||||
|
||||
aliasList->count = 1;
|
||||
if (!infoData.is_object())
|
||||
{
|
||||
Components::Logger::Error("Failed to load sound %s!", name.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
std::string errors;
|
||||
json11::Json infoData = json11::Json::parse(aliasFile.getBuffer(), errors);
|
||||
aliasList->head->soundFile = builder->getAllocator()->allocate<Game::SoundFile>();
|
||||
if (!aliasList->head->soundFile)
|
||||
{
|
||||
Components::Logger::Print("Error allocating memory for sound alias structure!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!infoData.is_object())
|
||||
{
|
||||
Components::Logger::Error("Failed to load sound %s!", name.data());
|
||||
return;
|
||||
}
|
||||
Game::snd_alias_t* alias = aliasList->head;
|
||||
|
||||
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
|
||||
auto type = infoData["type"];
|
||||
auto subtitle = infoData["subtitle"];
|
||||
auto secondaryAliasName = infoData["secondaryAliasName"];
|
||||
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"];
|
||||
// Fix casing
|
||||
if (soundFile.is_null())
|
||||
{
|
||||
soundFile = head["soundfile"];
|
||||
|
||||
if (type.is_null() || soundFile.is_null())
|
||||
{
|
||||
Components::Logger::Error("Failed to parse sound %s! Each alias must have at least a type and a soundFile", name.data());
|
||||
return;
|
||||
}
|
||||
Components::Logger::Print("Fixed casing on %s\n", name.c_str());
|
||||
}
|
||||
|
||||
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())
|
||||
|
||||
// TODO: actually support all of those properties
|
||||
if (CHECK(type, 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, string))
|
||||
{
|
||||
|
||||
alias->soundFile->exists = true;
|
||||
|
||||
if (subtitle.is_string())
|
||||
// TODO: actually support all of those properties
|
||||
if (!CHECK(type, number))
|
||||
{
|
||||
alias->subtitle = subtitle.string_value().data();
|
||||
}
|
||||
if (secondaryAliasName.is_string())
|
||||
{
|
||||
alias->secondaryAliasName = secondaryAliasName.string_value().data();
|
||||
}
|
||||
if (chainAliasName.is_string())
|
||||
{
|
||||
alias->chainAliasName = chainAliasName.string_value().data();
|
||||
Components::Logger::Print("%s is not number but %d (%s)\n", "type", type.type(), type.dump().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());
|
||||
|
||||
if (volumeFalloffCurve.is_string())
|
||||
if (!CHECK(subtitle, 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;
|
||||
alias->soundFile->u.loadSnd = Components::AssetHandler::FindAssetForZone(Game::XAssetType::ASSET_TYPE_LOADED_SOUND, soundFile.string_value(), builder).loadSnd;
|
||||
Components::Logger::Print("%s is not string but %d (%s)\n", "aliasName", aliasName.type(), aliasName.dump().c_str());
|
||||
}
|
||||
else if (type.string_value() == "streamed"s)
|
||||
|
||||
if (!CHECK(secondaryAliasName, string))
|
||||
{
|
||||
alias->soundFile->type = Game::SAT_STREAMED;
|
||||
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());
|
||||
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", "secondaryAliasName", secondaryAliasName.type(), secondaryAliasName.dump().c_str());
|
||||
}
|
||||
|
||||
if (!CHECK(chainAliasName, string))
|
||||
{
|
||||
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
|
||||
{
|
||||
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
|
||||
{
|
||||
Components::Logger::Error("Failed to parse sound %s!", name.data());
|
||||
return;
|
||||
}
|
||||
|
||||
header->sound = aliasList;
|
||||
|
||||
#undef CHECK
|
||||
|
||||
@ -155,7 +351,7 @@ namespace Assets
|
||||
{
|
||||
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];
|
||||
|
||||
@ -166,7 +362,12 @@ namespace Assets
|
||||
|
||||
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>();
|
||||
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* alias = &asset->head[i];
|
||||
|
@ -739,6 +739,22 @@ namespace Components
|
||||
|
||||
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()
|
||||
{
|
||||
@ -778,6 +794,15 @@ namespace Components
|
||||
// disable turrets on CoD:OL 448+ maps for now
|
||||
Utils::Hook(0x5EE577, Maps::G_SpawnTurretHook, HOOK_CALL).install()->quick();
|
||||
Utils::Hook(0x44A4D5, Maps::G_SpawnTurretHook, HOOK_CALL).install()->quick();
|
||||
|
||||
#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
|
||||
#if !defined(DEBUG) || !defined(SORT_SMODELS)
|
||||
|
@ -120,5 +120,7 @@ namespace Components
|
||||
static void SetSpecularStub1();
|
||||
static void SetSpecularStub2();
|
||||
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([]()
|
||||
{
|
||||
if (!Game::CL_IsCgameInitialized() || !Dvar::Var("r_drawAabbTrees").get<bool>()) return;
|
||||
|
||||
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::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
|
||||
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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -411,7 +411,7 @@ namespace Components
|
||||
{
|
||||
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()
|
||||
|
@ -44,7 +44,7 @@ namespace Components
|
||||
|
||||
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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -419,6 +419,8 @@ namespace Game
|
||||
|
||||
clientstate_t* clcState = reinterpret_cast<clientstate_t*>(0xB2C540);
|
||||
|
||||
GfxScene* scene = reinterpret_cast<GfxScene*>(0x6944914);
|
||||
|
||||
XAssetHeader ReallocateAssetPool(XAssetType type, unsigned int newSize)
|
||||
{
|
||||
int elSize = DB_GetXAssetSizeHandlers[type]();
|
||||
@ -728,6 +730,29 @@ namespace Game
|
||||
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)
|
||||
{
|
||||
DWORD* specular1 = reinterpret_cast<DWORD*>(0x69F105C);
|
||||
@ -806,6 +831,73 @@ namespace Game
|
||||
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)
|
||||
__declspec(naked) float UI_GetScoreboardLeft(void* /*a1*/)
|
||||
{
|
||||
|
@ -858,6 +858,8 @@ namespace Game
|
||||
|
||||
extern clientstate_t* clcState;
|
||||
|
||||
extern GfxScene* scene;
|
||||
|
||||
XAssetHeader ReallocateAssetPool(XAssetType type, unsigned int newSize);
|
||||
void Menu_FreeItemMemory(Game::itemDef_s* item);
|
||||
const char* TableLookup(StringTable* stringtable, int row, int column);
|
||||
@ -906,9 +908,12 @@ namespace Game
|
||||
void Vec3Normalize(vec3_t& vec);
|
||||
void Vec2UnpackTexCoords(const PackedTexCoords in, vec2_t* out);
|
||||
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 R_AddDebugLine(float* color, float* v1, float* v2);
|
||||
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, const float(*quat)[4]);
|
||||
}
|
||||
|
@ -906,7 +906,7 @@ namespace Game
|
||||
|
||||
struct MSSChannelMap
|
||||
{
|
||||
int speakerCount;
|
||||
unsigned int speakerCount;
|
||||
MSSSpeakerLevels speakers[6];
|
||||
};
|
||||
|
||||
@ -950,7 +950,7 @@ namespace Game
|
||||
{
|
||||
const char *aliasName;
|
||||
snd_alias_t *head;
|
||||
int count;
|
||||
unsigned int count;
|
||||
};
|
||||
|
||||
struct cStaticModel_s
|
||||
@ -4474,18 +4474,148 @@ namespace Game
|
||||
char pad3[724];
|
||||
} 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;
|
||||
unsigned char pad[308]; // 4
|
||||
float origin[3]; // 312
|
||||
float angles[3]; // 324
|
||||
char pad2[8];
|
||||
int eType;
|
||||
LerpEntityState lerp;
|
||||
int time2;
|
||||
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
|
||||
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 pad4;
|
||||
unsigned char pad5[248];
|
||||
unsigned __int16 script_classname;
|
||||
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;
|
||||
|
||||
#pragma pack(push, 1)
|
||||
@ -4829,6 +4959,310 @@ namespace Game
|
||||
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
|
||||
|
||||
#ifndef IDA
|
||||
|
@ -5,8 +5,8 @@
|
||||
|
||||
#ifndef RC_INVOKED
|
||||
|
||||
#define _HAS_CXX17 1
|
||||
#define _HAS_CXX20 1
|
||||
//#define _HAS_CXX17 1
|
||||
//#define _HAS_CXX20 1
|
||||
#define VC_EXTRALEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
@ -38,6 +38,7 @@
|
||||
#include <future>
|
||||
#include <unordered_map>
|
||||
#include <queue>
|
||||
#include <algorithm>
|
||||
|
||||
// Experimental C++17 features
|
||||
#include <filesystem>
|
||||
|
Loading…
Reference in New Issue
Block a user