diff --git a/src/Common/Game/IW5/IW5.h b/src/Common/Game/IW5/IW5.h index 01917beb..e6c58928 100644 --- a/src/Common/Game/IW5/IW5.h +++ b/src/Common/Game/IW5/IW5.h @@ -118,6 +118,9 @@ namespace IW5 WFT_ATTACHMENT, WFT_ANIM_OVERRIDES, WFT_SOUND_OVERRIDES, + WFT_FX_OVERRIDES, + WFT_RELOAD_OVERRIDES, + WFT_NOTE_TRACK_OVERRIDES, WFT_NUM_FIELD_TYPES, }; diff --git a/src/Common/Game/IW5/IW5_Assets.h b/src/Common/Game/IW5/IW5_Assets.h index 67c224b3..8084e044 100644 --- a/src/Common/Game/IW5/IW5_Assets.h +++ b/src/Common/Game/IW5/IW5_Assets.h @@ -3943,13 +3943,24 @@ namespace IW5 SoundOverrideTypes soundType; }; + enum FXOverrideTypes : unsigned int + { + FXTYPE_NONE = 0x0, + FXTYPE_VIEW_FLASH = 0x1, + FXTYPE_WORLD_FLASH = 0x2, + FXTYPE_VIEW_SHELL_EJECT = 0x3, + FXTYPE_WORLD_SHELL_EJECT = 0x4, + + FXTYPE_COUNT + }; + struct FXOverrideEntry { - unsigned short attachment1; - unsigned short attachment2; + WeaponAttachmentCombination attachment1; + WeaponAttachmentCombination attachment2; FxEffectDef* overrideFX; FxEffectDef* altmodeFX; - unsigned int fxType; + FXOverrideTypes fxType; }; struct ReloadStateTimerEntry diff --git a/src/ObjCommon/Game/IW5/InfoString/WeaponFields.h b/src/ObjCommon/Game/IW5/InfoString/WeaponFields.h index b75514df..1d762862 100644 --- a/src/ObjCommon/Game/IW5/InfoString/WeaponFields.h +++ b/src/ObjCommon/Game/IW5/InfoString/WeaponFields.h @@ -4,7 +4,6 @@ namespace IW5 { // WeaponCompleteDef: - // TODO: fxOverrides // TODO: reloadOverrides // TODO: notetrackOverrides // TODO: iFireTimeAkimbo @@ -734,6 +733,7 @@ namespace IW5 {"attachments", offsetof(WeaponFullDef, scopes), WFT_ATTACHMENT }, {"animOverrides", offsetof(WeaponFullDef, weapCompleteDef.animOverrides), WFT_ANIM_OVERRIDES }, {"soundOverrides", offsetof(WeaponFullDef, weapCompleteDef.soundOverrides), WFT_SOUND_OVERRIDES }, + {"fxOverrides", offsetof(WeaponFullDef, weapCompleteDef.fxOverrides), WFT_FX_OVERRIDES }, }; inline const char* szWeapTypeNames[]{ @@ -934,4 +934,13 @@ namespace IW5 "player_lastshot", }; static_assert(std::extent_v == SNDTYPE_PLAYER_COUNT); + + inline const char* fxOverrideTypeNames[]{ + "none", + "view_flash", + "world_flash", + "view_shell_eject", + "world_shell_eject", + }; + static_assert(std::extent_v == FXTYPE_COUNT); } // namespace IW5 diff --git a/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperWeapon.cpp b/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperWeapon.cpp index 6cf3167f..9599b95d 100644 --- a/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperWeapon.cpp +++ b/src/ObjWriting/Game/IW5/AssetDumpers/AssetDumperWeapon.cpp @@ -225,6 +225,10 @@ namespace IW5 FillFromSoundOverrides(std::string(field.szName)); break; + case WFT_FX_OVERRIDES: + FillFromFxOverrides(std::string(field.szName)); + break; + case WFT_NUM_FIELD_TYPES: default: assert(false); @@ -410,6 +414,55 @@ namespace IW5 m_info_string.SetValueForKey(key, ss.str()); } + void FillFromFxOverrides(const std::string& key) + { + std::stringstream ss; + bool first = true; + + for (auto i = 0u; i < m_weapon->weapCompleteDef.numFXOverrides; i++) + { + const auto& fxOverride = m_weapon->weapCompleteDef.fxOverrides[i]; + + if (!first) + ss << "\n"; + else + first = false; + + assert(fxOverride.fxType < FXTYPE_COUNT); + + if (fxOverride.attachment1.fields) + ss << GetNameForSingleWeaponAttachment(fxOverride.attachment1); + else + ss << "none"; + + ss << ' '; + + if (fxOverride.attachment2.fields) + ss << GetNameForSingleWeaponAttachment(fxOverride.attachment2); + else + ss << "none"; + + ss << ' '; + + if (fxOverride.fxType < FXTYPE_COUNT) + ss << fxOverrideTypeNames[fxOverride.fxType] << ' '; + + if (fxOverride.overrideFX && fxOverride.overrideFX->name && fxOverride.overrideFX->name[0]) + ss << fxOverride.overrideFX->name; + else + ss << "none"; + + ss << ' '; + + if (fxOverride.altmodeFX && fxOverride.altmodeFX->name && fxOverride.altmodeFX->name[0]) + ss << fxOverride.altmodeFX->name; + else + ss << "none"; + } + + m_info_string.SetValueForKey(key, ss.str()); + } + const WeaponFullDef* m_weapon; }; } // namespace IW5