mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2025-04-20 08:05:45 +00:00
feat: load iw4 weapons from raw
This commit is contained in:
parent
2650669200
commit
a1cf4ef30b
@ -113,6 +113,9 @@ namespace IW4
|
|||||||
WFT_NOTETRACKSOUNDMAP,
|
WFT_NOTETRACKSOUNDMAP,
|
||||||
WFT_NOTETRACKRUMBLEMAP,
|
WFT_NOTETRACKRUMBLEMAP,
|
||||||
|
|
||||||
|
// Custom
|
||||||
|
WFT_ANIM_NAME,
|
||||||
|
|
||||||
WFT_NUM_FIELD_TYPES,
|
WFT_NUM_FIELD_TYPES,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -173,4 +173,10 @@ namespace IW4
|
|||||||
"rear",
|
"rear",
|
||||||
"all",
|
"all",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline const char* bounceSoundSuffixes[]{
|
||||||
|
"_default", "_bark", "_brick", "_carpet", "_cloth", "_concrete", "_dirt", "_flesh", "_foliage", "_glass", "_grass",
|
||||||
|
"_gravel", "_ice", "_metal", "_mud", "_paper", "_plaster", "_rock", "_sand", "_snow", "_water", "_wood",
|
||||||
|
"_asphalt", "_ceramic", "_plastic", "_rubber", "_cushion", "_fruit", "_painted_metal", "_riot_shield", "_slush",
|
||||||
|
};
|
||||||
} // namespace IW4
|
} // namespace IW4
|
||||||
|
@ -28,114 +28,114 @@ namespace IW4
|
|||||||
{"hideTags", offsetof(WeaponFullDef, hideTags), WFT_HIDETAGS },
|
{"hideTags", offsetof(WeaponFullDef, hideTags), WFT_HIDETAGS },
|
||||||
{"notetrackSoundMap", offsetof(WeaponFullDef, notetrackSoundMapKeys), WFT_NOTETRACKSOUNDMAP },
|
{"notetrackSoundMap", offsetof(WeaponFullDef, notetrackSoundMapKeys), WFT_NOTETRACKSOUNDMAP },
|
||||||
{"notetrackRumbleMap", offsetof(WeaponFullDef, notetrackRumbleMapKeys), WFT_NOTETRACKRUMBLEMAP },
|
{"notetrackRumbleMap", offsetof(WeaponFullDef, notetrackRumbleMapKeys), WFT_NOTETRACKRUMBLEMAP },
|
||||||
{"idleAnim", offsetof(WeaponFullDef, szXAnims[WEAP_ANIM_IDLE]), CSPFT_STRING },
|
{"idleAnim", offsetof(WeaponFullDef, szXAnims[WEAP_ANIM_IDLE]), WFT_ANIM_NAME },
|
||||||
{"emptyIdleAnim", offsetof(WeaponFullDef, szXAnims[WEAP_ANIM_EMPTY_IDLE]), CSPFT_STRING },
|
{"emptyIdleAnim", offsetof(WeaponFullDef, szXAnims[WEAP_ANIM_EMPTY_IDLE]), WFT_ANIM_NAME },
|
||||||
{"fireAnim", offsetof(WeaponFullDef, szXAnims[WEAP_ANIM_FIRE]), CSPFT_STRING },
|
{"fireAnim", offsetof(WeaponFullDef, szXAnims[WEAP_ANIM_FIRE]), WFT_ANIM_NAME },
|
||||||
{"holdFireAnim", offsetof(WeaponFullDef, szXAnims[WEAP_ANIM_HOLD_FIRE]), CSPFT_STRING },
|
{"holdFireAnim", offsetof(WeaponFullDef, szXAnims[WEAP_ANIM_HOLD_FIRE]), WFT_ANIM_NAME },
|
||||||
{"lastShotAnim", offsetof(WeaponFullDef, szXAnims[WEAP_ANIM_LASTSHOT]), CSPFT_STRING },
|
{"lastShotAnim", offsetof(WeaponFullDef, szXAnims[WEAP_ANIM_LASTSHOT]), WFT_ANIM_NAME },
|
||||||
{"detonateAnim", offsetof(WeaponFullDef, szXAnims[WEAP_ANIM_DETONATE]), CSPFT_STRING },
|
{"detonateAnim", offsetof(WeaponFullDef, szXAnims[WEAP_ANIM_DETONATE]), WFT_ANIM_NAME },
|
||||||
{"rechamberAnim", offsetof(WeaponFullDef, szXAnims[WEAP_ANIM_RECHAMBER]), CSPFT_STRING },
|
{"rechamberAnim", offsetof(WeaponFullDef, szXAnims[WEAP_ANIM_RECHAMBER]), WFT_ANIM_NAME },
|
||||||
{"meleeAnim", offsetof(WeaponFullDef, szXAnims[WEAP_ANIM_MELEE]), CSPFT_STRING },
|
{"meleeAnim", offsetof(WeaponFullDef, szXAnims[WEAP_ANIM_MELEE]), WFT_ANIM_NAME },
|
||||||
{"meleeChargeAnim", offsetof(WeaponFullDef, szXAnims[WEAP_ANIM_MELEE_CHARGE]), CSPFT_STRING },
|
{"meleeChargeAnim", offsetof(WeaponFullDef, szXAnims[WEAP_ANIM_MELEE_CHARGE]), WFT_ANIM_NAME },
|
||||||
{"reloadAnim", offsetof(WeaponFullDef, szXAnims[WEAP_ANIM_RELOAD]), CSPFT_STRING },
|
{"reloadAnim", offsetof(WeaponFullDef, szXAnims[WEAP_ANIM_RELOAD]), WFT_ANIM_NAME },
|
||||||
{"reloadEmptyAnim", offsetof(WeaponFullDef, szXAnims[WEAP_ANIM_RELOAD_EMPTY]), CSPFT_STRING },
|
{"reloadEmptyAnim", offsetof(WeaponFullDef, szXAnims[WEAP_ANIM_RELOAD_EMPTY]), WFT_ANIM_NAME },
|
||||||
{"reloadStartAnim", offsetof(WeaponFullDef, szXAnims[WEAP_ANIM_RELOAD_START]), CSPFT_STRING },
|
{"reloadStartAnim", offsetof(WeaponFullDef, szXAnims[WEAP_ANIM_RELOAD_START]), WFT_ANIM_NAME },
|
||||||
{"reloadEndAnim", offsetof(WeaponFullDef, szXAnims[WEAP_ANIM_RELOAD_END]), CSPFT_STRING },
|
{"reloadEndAnim", offsetof(WeaponFullDef, szXAnims[WEAP_ANIM_RELOAD_END]), WFT_ANIM_NAME },
|
||||||
{"raiseAnim", offsetof(WeaponFullDef, szXAnims[WEAP_ANIM_RAISE]), CSPFT_STRING },
|
{"raiseAnim", offsetof(WeaponFullDef, szXAnims[WEAP_ANIM_RAISE]), WFT_ANIM_NAME },
|
||||||
{"dropAnim", offsetof(WeaponFullDef, szXAnims[WEAP_ANIM_DROP]), CSPFT_STRING },
|
{"dropAnim", offsetof(WeaponFullDef, szXAnims[WEAP_ANIM_DROP]), WFT_ANIM_NAME },
|
||||||
{"firstRaiseAnim", offsetof(WeaponFullDef, szXAnims[WEAP_ANIM_FIRST_RAISE]), CSPFT_STRING },
|
{"firstRaiseAnim", offsetof(WeaponFullDef, szXAnims[WEAP_ANIM_FIRST_RAISE]), WFT_ANIM_NAME },
|
||||||
{"breachRaiseAnim", offsetof(WeaponFullDef, szXAnims[WEAP_ANIM_BREACH_RAISE]), CSPFT_STRING },
|
{"breachRaiseAnim", offsetof(WeaponFullDef, szXAnims[WEAP_ANIM_BREACH_RAISE]), WFT_ANIM_NAME },
|
||||||
{"altRaiseAnim", offsetof(WeaponFullDef, szXAnims[WEAP_ANIM_ALT_RAISE]), CSPFT_STRING },
|
{"altRaiseAnim", offsetof(WeaponFullDef, szXAnims[WEAP_ANIM_ALT_RAISE]), WFT_ANIM_NAME },
|
||||||
{"altDropAnim", offsetof(WeaponFullDef, szXAnims[WEAP_ANIM_ALT_DROP]), CSPFT_STRING },
|
{"altDropAnim", offsetof(WeaponFullDef, szXAnims[WEAP_ANIM_ALT_DROP]), WFT_ANIM_NAME },
|
||||||
{"quickRaiseAnim", offsetof(WeaponFullDef, szXAnims[WEAP_ANIM_QUICK_RAISE]), CSPFT_STRING },
|
{"quickRaiseAnim", offsetof(WeaponFullDef, szXAnims[WEAP_ANIM_QUICK_RAISE]), WFT_ANIM_NAME },
|
||||||
{"quickDropAnim", offsetof(WeaponFullDef, szXAnims[WEAP_ANIM_QUICK_DROP]), CSPFT_STRING },
|
{"quickDropAnim", offsetof(WeaponFullDef, szXAnims[WEAP_ANIM_QUICK_DROP]), WFT_ANIM_NAME },
|
||||||
{"emptyRaiseAnim", offsetof(WeaponFullDef, szXAnims[WEAP_ANIM_EMPTY_RAISE]), CSPFT_STRING },
|
{"emptyRaiseAnim", offsetof(WeaponFullDef, szXAnims[WEAP_ANIM_EMPTY_RAISE]), WFT_ANIM_NAME },
|
||||||
{"emptyDropAnim", offsetof(WeaponFullDef, szXAnims[WEAP_ANIM_EMPTY_DROP]), CSPFT_STRING },
|
{"emptyDropAnim", offsetof(WeaponFullDef, szXAnims[WEAP_ANIM_EMPTY_DROP]), WFT_ANIM_NAME },
|
||||||
{"sprintInAnim", offsetof(WeaponFullDef, szXAnims[WEAP_ANIM_SPRINT_IN]), CSPFT_STRING },
|
{"sprintInAnim", offsetof(WeaponFullDef, szXAnims[WEAP_ANIM_SPRINT_IN]), WFT_ANIM_NAME },
|
||||||
{"sprintLoopAnim", offsetof(WeaponFullDef, szXAnims[WEAP_ANIM_SPRINT_LOOP]), CSPFT_STRING },
|
{"sprintLoopAnim", offsetof(WeaponFullDef, szXAnims[WEAP_ANIM_SPRINT_LOOP]), WFT_ANIM_NAME },
|
||||||
{"sprintOutAnim", offsetof(WeaponFullDef, szXAnims[WEAP_ANIM_SPRINT_OUT]), CSPFT_STRING },
|
{"sprintOutAnim", offsetof(WeaponFullDef, szXAnims[WEAP_ANIM_SPRINT_OUT]), WFT_ANIM_NAME },
|
||||||
{"stunnedAnimStart", offsetof(WeaponFullDef, szXAnims[WEAP_ANIM_STUNNED_START]), CSPFT_STRING },
|
{"stunnedAnimStart", offsetof(WeaponFullDef, szXAnims[WEAP_ANIM_STUNNED_START]), WFT_ANIM_NAME },
|
||||||
{"stunnedAnimLoop", offsetof(WeaponFullDef, szXAnims[WEAP_ANIM_STUNNED_LOOP]), CSPFT_STRING },
|
{"stunnedAnimLoop", offsetof(WeaponFullDef, szXAnims[WEAP_ANIM_STUNNED_LOOP]), WFT_ANIM_NAME },
|
||||||
{"stunnedAnimEnd", offsetof(WeaponFullDef, szXAnims[WEAP_ANIM_STUNNED_END]), CSPFT_STRING },
|
{"stunnedAnimEnd", offsetof(WeaponFullDef, szXAnims[WEAP_ANIM_STUNNED_END]), WFT_ANIM_NAME },
|
||||||
{"nightVisionWearAnim", offsetof(WeaponFullDef, szXAnims[WEAP_ANIM_NIGHTVISION_WEAR]), CSPFT_STRING },
|
{"nightVisionWearAnim", offsetof(WeaponFullDef, szXAnims[WEAP_ANIM_NIGHTVISION_WEAR]), WFT_ANIM_NAME },
|
||||||
{"nightVisionRemoveAnim", offsetof(WeaponFullDef, szXAnims[WEAP_ANIM_NIGHTVISION_REMOVE]), CSPFT_STRING },
|
{"nightVisionRemoveAnim", offsetof(WeaponFullDef, szXAnims[WEAP_ANIM_NIGHTVISION_REMOVE]), WFT_ANIM_NAME },
|
||||||
{"adsFireAnim", offsetof(WeaponFullDef, szXAnims[WEAP_ANIM_ADS_FIRE]), CSPFT_STRING },
|
{"adsFireAnim", offsetof(WeaponFullDef, szXAnims[WEAP_ANIM_ADS_FIRE]), WFT_ANIM_NAME },
|
||||||
{"adsLastShotAnim", offsetof(WeaponFullDef, szXAnims[WEAP_ANIM_ADS_LASTSHOT]), CSPFT_STRING },
|
{"adsLastShotAnim", offsetof(WeaponFullDef, szXAnims[WEAP_ANIM_ADS_LASTSHOT]), WFT_ANIM_NAME },
|
||||||
{"adsRechamberAnim", offsetof(WeaponFullDef, szXAnims[WEAP_ANIM_ADS_RECHAMBER]), CSPFT_STRING },
|
{"adsRechamberAnim", offsetof(WeaponFullDef, szXAnims[WEAP_ANIM_ADS_RECHAMBER]), WFT_ANIM_NAME },
|
||||||
{"adsUpAnim", offsetof(WeaponFullDef, szXAnims[WEAP_ANIM_ADS_UP]), CSPFT_STRING },
|
{"adsUpAnim", offsetof(WeaponFullDef, szXAnims[WEAP_ANIM_ADS_UP]), WFT_ANIM_NAME },
|
||||||
{"adsDownAnim", offsetof(WeaponFullDef, szXAnims[WEAP_ANIM_ADS_DOWN]), CSPFT_STRING },
|
{"adsDownAnim", offsetof(WeaponFullDef, szXAnims[WEAP_ANIM_ADS_DOWN]), WFT_ANIM_NAME },
|
||||||
{"idleAnimR", offsetof(WeaponFullDef, szXAnimsRightHanded[WEAP_ANIM_IDLE]), CSPFT_STRING },
|
{"idleAnimR", offsetof(WeaponFullDef, szXAnimsRightHanded[WEAP_ANIM_IDLE]), WFT_ANIM_NAME },
|
||||||
{"emptyIdleAnimR", offsetof(WeaponFullDef, szXAnimsRightHanded[WEAP_ANIM_EMPTY_IDLE]), CSPFT_STRING },
|
{"emptyIdleAnimR", offsetof(WeaponFullDef, szXAnimsRightHanded[WEAP_ANIM_EMPTY_IDLE]), WFT_ANIM_NAME },
|
||||||
{"fireAnimR", offsetof(WeaponFullDef, szXAnimsRightHanded[WEAP_ANIM_FIRE]), CSPFT_STRING },
|
{"fireAnimR", offsetof(WeaponFullDef, szXAnimsRightHanded[WEAP_ANIM_FIRE]), WFT_ANIM_NAME },
|
||||||
{"holdFireAnimR", offsetof(WeaponFullDef, szXAnimsRightHanded[WEAP_ANIM_HOLD_FIRE]), CSPFT_STRING },
|
{"holdFireAnimR", offsetof(WeaponFullDef, szXAnimsRightHanded[WEAP_ANIM_HOLD_FIRE]), WFT_ANIM_NAME },
|
||||||
{"lastShotAnimR", offsetof(WeaponFullDef, szXAnimsRightHanded[WEAP_ANIM_LASTSHOT]), CSPFT_STRING },
|
{"lastShotAnimR", offsetof(WeaponFullDef, szXAnimsRightHanded[WEAP_ANIM_LASTSHOT]), WFT_ANIM_NAME },
|
||||||
{"detonateAnimR", offsetof(WeaponFullDef, szXAnimsRightHanded[WEAP_ANIM_DETONATE]), CSPFT_STRING },
|
{"detonateAnimR", offsetof(WeaponFullDef, szXAnimsRightHanded[WEAP_ANIM_DETONATE]), WFT_ANIM_NAME },
|
||||||
{"rechamberAnimR", offsetof(WeaponFullDef, szXAnimsRightHanded[WEAP_ANIM_RECHAMBER]), CSPFT_STRING },
|
{"rechamberAnimR", offsetof(WeaponFullDef, szXAnimsRightHanded[WEAP_ANIM_RECHAMBER]), WFT_ANIM_NAME },
|
||||||
{"meleeAnimR", offsetof(WeaponFullDef, szXAnimsRightHanded[WEAP_ANIM_MELEE]), CSPFT_STRING },
|
{"meleeAnimR", offsetof(WeaponFullDef, szXAnimsRightHanded[WEAP_ANIM_MELEE]), WFT_ANIM_NAME },
|
||||||
{"meleeChargeAnimR", offsetof(WeaponFullDef, szXAnimsRightHanded[WEAP_ANIM_MELEE_CHARGE]), CSPFT_STRING },
|
{"meleeChargeAnimR", offsetof(WeaponFullDef, szXAnimsRightHanded[WEAP_ANIM_MELEE_CHARGE]), WFT_ANIM_NAME },
|
||||||
{"reloadAnimR", offsetof(WeaponFullDef, szXAnimsRightHanded[WEAP_ANIM_RELOAD]), CSPFT_STRING },
|
{"reloadAnimR", offsetof(WeaponFullDef, szXAnimsRightHanded[WEAP_ANIM_RELOAD]), WFT_ANIM_NAME },
|
||||||
{"reloadEmptyAnimR", offsetof(WeaponFullDef, szXAnimsRightHanded[WEAP_ANIM_RELOAD_EMPTY]), CSPFT_STRING },
|
{"reloadEmptyAnimR", offsetof(WeaponFullDef, szXAnimsRightHanded[WEAP_ANIM_RELOAD_EMPTY]), WFT_ANIM_NAME },
|
||||||
{"reloadStartAnimR", offsetof(WeaponFullDef, szXAnimsRightHanded[WEAP_ANIM_RELOAD_START]), CSPFT_STRING },
|
{"reloadStartAnimR", offsetof(WeaponFullDef, szXAnimsRightHanded[WEAP_ANIM_RELOAD_START]), WFT_ANIM_NAME },
|
||||||
{"reloadEndAnimR", offsetof(WeaponFullDef, szXAnimsRightHanded[WEAP_ANIM_RELOAD_END]), CSPFT_STRING },
|
{"reloadEndAnimR", offsetof(WeaponFullDef, szXAnimsRightHanded[WEAP_ANIM_RELOAD_END]), WFT_ANIM_NAME },
|
||||||
{"raiseAnimR", offsetof(WeaponFullDef, szXAnimsRightHanded[WEAP_ANIM_RAISE]), CSPFT_STRING },
|
{"raiseAnimR", offsetof(WeaponFullDef, szXAnimsRightHanded[WEAP_ANIM_RAISE]), WFT_ANIM_NAME },
|
||||||
{"dropAnimR", offsetof(WeaponFullDef, szXAnimsRightHanded[WEAP_ANIM_DROP]), CSPFT_STRING },
|
{"dropAnimR", offsetof(WeaponFullDef, szXAnimsRightHanded[WEAP_ANIM_DROP]), WFT_ANIM_NAME },
|
||||||
{"firstRaiseAnimR", offsetof(WeaponFullDef, szXAnimsRightHanded[WEAP_ANIM_FIRST_RAISE]), CSPFT_STRING },
|
{"firstRaiseAnimR", offsetof(WeaponFullDef, szXAnimsRightHanded[WEAP_ANIM_FIRST_RAISE]), WFT_ANIM_NAME },
|
||||||
{"breachRaiseAnimR", offsetof(WeaponFullDef, szXAnimsRightHanded[WEAP_ANIM_BREACH_RAISE]), CSPFT_STRING },
|
{"breachRaiseAnimR", offsetof(WeaponFullDef, szXAnimsRightHanded[WEAP_ANIM_BREACH_RAISE]), WFT_ANIM_NAME },
|
||||||
{"altRaiseAnimR", offsetof(WeaponFullDef, szXAnimsRightHanded[WEAP_ANIM_ALT_RAISE]), CSPFT_STRING },
|
{"altRaiseAnimR", offsetof(WeaponFullDef, szXAnimsRightHanded[WEAP_ANIM_ALT_RAISE]), WFT_ANIM_NAME },
|
||||||
{"altDropAnimR", offsetof(WeaponFullDef, szXAnimsRightHanded[WEAP_ANIM_ALT_DROP]), CSPFT_STRING },
|
{"altDropAnimR", offsetof(WeaponFullDef, szXAnimsRightHanded[WEAP_ANIM_ALT_DROP]), WFT_ANIM_NAME },
|
||||||
{"quickRaiseAnimR", offsetof(WeaponFullDef, szXAnimsRightHanded[WEAP_ANIM_QUICK_RAISE]), CSPFT_STRING },
|
{"quickRaiseAnimR", offsetof(WeaponFullDef, szXAnimsRightHanded[WEAP_ANIM_QUICK_RAISE]), WFT_ANIM_NAME },
|
||||||
{"quickDropAnimR", offsetof(WeaponFullDef, szXAnimsRightHanded[WEAP_ANIM_QUICK_DROP]), CSPFT_STRING },
|
{"quickDropAnimR", offsetof(WeaponFullDef, szXAnimsRightHanded[WEAP_ANIM_QUICK_DROP]), WFT_ANIM_NAME },
|
||||||
{"emptyRaiseAnimR", offsetof(WeaponFullDef, szXAnimsRightHanded[WEAP_ANIM_EMPTY_RAISE]), CSPFT_STRING },
|
{"emptyRaiseAnimR", offsetof(WeaponFullDef, szXAnimsRightHanded[WEAP_ANIM_EMPTY_RAISE]), WFT_ANIM_NAME },
|
||||||
{"emptyDropAnimR", offsetof(WeaponFullDef, szXAnimsRightHanded[WEAP_ANIM_EMPTY_DROP]), CSPFT_STRING },
|
{"emptyDropAnimR", offsetof(WeaponFullDef, szXAnimsRightHanded[WEAP_ANIM_EMPTY_DROP]), WFT_ANIM_NAME },
|
||||||
{"sprintInAnimR", offsetof(WeaponFullDef, szXAnimsRightHanded[WEAP_ANIM_SPRINT_IN]), CSPFT_STRING },
|
{"sprintInAnimR", offsetof(WeaponFullDef, szXAnimsRightHanded[WEAP_ANIM_SPRINT_IN]), WFT_ANIM_NAME },
|
||||||
{"sprintLoopAnimR", offsetof(WeaponFullDef, szXAnimsRightHanded[WEAP_ANIM_SPRINT_LOOP]), CSPFT_STRING },
|
{"sprintLoopAnimR", offsetof(WeaponFullDef, szXAnimsRightHanded[WEAP_ANIM_SPRINT_LOOP]), WFT_ANIM_NAME },
|
||||||
{"sprintOutAnimR", offsetof(WeaponFullDef, szXAnimsRightHanded[WEAP_ANIM_SPRINT_OUT]), CSPFT_STRING },
|
{"sprintOutAnimR", offsetof(WeaponFullDef, szXAnimsRightHanded[WEAP_ANIM_SPRINT_OUT]), WFT_ANIM_NAME },
|
||||||
{"stunnedAnimStartR", offsetof(WeaponFullDef, szXAnimsRightHanded[WEAP_ANIM_STUNNED_START]), CSPFT_STRING },
|
{"stunnedAnimStartR", offsetof(WeaponFullDef, szXAnimsRightHanded[WEAP_ANIM_STUNNED_START]), WFT_ANIM_NAME },
|
||||||
{"stunnedAnimLoopR", offsetof(WeaponFullDef, szXAnimsRightHanded[WEAP_ANIM_STUNNED_LOOP]), CSPFT_STRING },
|
{"stunnedAnimLoopR", offsetof(WeaponFullDef, szXAnimsRightHanded[WEAP_ANIM_STUNNED_LOOP]), WFT_ANIM_NAME },
|
||||||
{"stunnedAnimEndR", offsetof(WeaponFullDef, szXAnimsRightHanded[WEAP_ANIM_STUNNED_END]), CSPFT_STRING },
|
{"stunnedAnimEndR", offsetof(WeaponFullDef, szXAnimsRightHanded[WEAP_ANIM_STUNNED_END]), WFT_ANIM_NAME },
|
||||||
{"nightVisionWearAnimR", offsetof(WeaponFullDef, szXAnimsRightHanded[WEAP_ANIM_NIGHTVISION_WEAR]), CSPFT_STRING },
|
{"nightVisionWearAnimR", offsetof(WeaponFullDef, szXAnimsRightHanded[WEAP_ANIM_NIGHTVISION_WEAR]), WFT_ANIM_NAME },
|
||||||
{"nightVisionRemoveAnimR", offsetof(WeaponFullDef, szXAnimsRightHanded[WEAP_ANIM_NIGHTVISION_REMOVE]), CSPFT_STRING },
|
{"nightVisionRemoveAnimR", offsetof(WeaponFullDef, szXAnimsRightHanded[WEAP_ANIM_NIGHTVISION_REMOVE]), WFT_ANIM_NAME },
|
||||||
{"adsFireAnimR", offsetof(WeaponFullDef, szXAnimsRightHanded[WEAP_ANIM_ADS_FIRE]), CSPFT_STRING },
|
{"adsFireAnimR", offsetof(WeaponFullDef, szXAnimsRightHanded[WEAP_ANIM_ADS_FIRE]), WFT_ANIM_NAME },
|
||||||
{"adsLastShotAnimR", offsetof(WeaponFullDef, szXAnimsRightHanded[WEAP_ANIM_ADS_LASTSHOT]), CSPFT_STRING },
|
{"adsLastShotAnimR", offsetof(WeaponFullDef, szXAnimsRightHanded[WEAP_ANIM_ADS_LASTSHOT]), WFT_ANIM_NAME },
|
||||||
{"adsRechamberAnimR", offsetof(WeaponFullDef, szXAnimsRightHanded[WEAP_ANIM_ADS_RECHAMBER]), CSPFT_STRING },
|
{"adsRechamberAnimR", offsetof(WeaponFullDef, szXAnimsRightHanded[WEAP_ANIM_ADS_RECHAMBER]), WFT_ANIM_NAME },
|
||||||
{"adsUpAnimR", offsetof(WeaponFullDef, szXAnimsRightHanded[WEAP_ANIM_ADS_UP]), CSPFT_STRING },
|
{"adsUpAnimR", offsetof(WeaponFullDef, szXAnimsRightHanded[WEAP_ANIM_ADS_UP]), WFT_ANIM_NAME },
|
||||||
{"adsDownAnimR", offsetof(WeaponFullDef, szXAnimsRightHanded[WEAP_ANIM_ADS_DOWN]), CSPFT_STRING },
|
{"adsDownAnimR", offsetof(WeaponFullDef, szXAnimsRightHanded[WEAP_ANIM_ADS_DOWN]), WFT_ANIM_NAME },
|
||||||
{"idleAnimL", offsetof(WeaponFullDef, szXAnimsLeftHanded[WEAP_ANIM_IDLE]), CSPFT_STRING },
|
{"idleAnimL", offsetof(WeaponFullDef, szXAnimsLeftHanded[WEAP_ANIM_IDLE]), WFT_ANIM_NAME },
|
||||||
{"emptyIdleAnimL", offsetof(WeaponFullDef, szXAnimsLeftHanded[WEAP_ANIM_EMPTY_IDLE]), CSPFT_STRING },
|
{"emptyIdleAnimL", offsetof(WeaponFullDef, szXAnimsLeftHanded[WEAP_ANIM_EMPTY_IDLE]), WFT_ANIM_NAME },
|
||||||
{"fireAnimL", offsetof(WeaponFullDef, szXAnimsLeftHanded[WEAP_ANIM_FIRE]), CSPFT_STRING },
|
{"fireAnimL", offsetof(WeaponFullDef, szXAnimsLeftHanded[WEAP_ANIM_FIRE]), WFT_ANIM_NAME },
|
||||||
{"holdFireAnimL", offsetof(WeaponFullDef, szXAnimsLeftHanded[WEAP_ANIM_HOLD_FIRE]), CSPFT_STRING },
|
{"holdFireAnimL", offsetof(WeaponFullDef, szXAnimsLeftHanded[WEAP_ANIM_HOLD_FIRE]), WFT_ANIM_NAME },
|
||||||
{"lastShotAnimL", offsetof(WeaponFullDef, szXAnimsLeftHanded[WEAP_ANIM_LASTSHOT]), CSPFT_STRING },
|
{"lastShotAnimL", offsetof(WeaponFullDef, szXAnimsLeftHanded[WEAP_ANIM_LASTSHOT]), WFT_ANIM_NAME },
|
||||||
{"detonateAnimL", offsetof(WeaponFullDef, szXAnimsLeftHanded[WEAP_ANIM_DETONATE]), CSPFT_STRING },
|
{"detonateAnimL", offsetof(WeaponFullDef, szXAnimsLeftHanded[WEAP_ANIM_DETONATE]), WFT_ANIM_NAME },
|
||||||
{"rechamberAnimL", offsetof(WeaponFullDef, szXAnimsLeftHanded[WEAP_ANIM_RECHAMBER]), CSPFT_STRING },
|
{"rechamberAnimL", offsetof(WeaponFullDef, szXAnimsLeftHanded[WEAP_ANIM_RECHAMBER]), WFT_ANIM_NAME },
|
||||||
{"meleeAnimL", offsetof(WeaponFullDef, szXAnimsLeftHanded[WEAP_ANIM_MELEE]), CSPFT_STRING },
|
{"meleeAnimL", offsetof(WeaponFullDef, szXAnimsLeftHanded[WEAP_ANIM_MELEE]), WFT_ANIM_NAME },
|
||||||
{"meleeChargeAnimL", offsetof(WeaponFullDef, szXAnimsLeftHanded[WEAP_ANIM_MELEE_CHARGE]), CSPFT_STRING },
|
{"meleeChargeAnimL", offsetof(WeaponFullDef, szXAnimsLeftHanded[WEAP_ANIM_MELEE_CHARGE]), WFT_ANIM_NAME },
|
||||||
{"reloadAnimL", offsetof(WeaponFullDef, szXAnimsLeftHanded[WEAP_ANIM_RELOAD]), CSPFT_STRING },
|
{"reloadAnimL", offsetof(WeaponFullDef, szXAnimsLeftHanded[WEAP_ANIM_RELOAD]), WFT_ANIM_NAME },
|
||||||
{"reloadEmptyAnimL", offsetof(WeaponFullDef, szXAnimsLeftHanded[WEAP_ANIM_RELOAD_EMPTY]), CSPFT_STRING },
|
{"reloadEmptyAnimL", offsetof(WeaponFullDef, szXAnimsLeftHanded[WEAP_ANIM_RELOAD_EMPTY]), WFT_ANIM_NAME },
|
||||||
{"reloadStartAnimL", offsetof(WeaponFullDef, szXAnimsLeftHanded[WEAP_ANIM_RELOAD_START]), CSPFT_STRING },
|
{"reloadStartAnimL", offsetof(WeaponFullDef, szXAnimsLeftHanded[WEAP_ANIM_RELOAD_START]), WFT_ANIM_NAME },
|
||||||
{"reloadEndAnimL", offsetof(WeaponFullDef, szXAnimsLeftHanded[WEAP_ANIM_RELOAD_END]), CSPFT_STRING },
|
{"reloadEndAnimL", offsetof(WeaponFullDef, szXAnimsLeftHanded[WEAP_ANIM_RELOAD_END]), WFT_ANIM_NAME },
|
||||||
{"raiseAnimL", offsetof(WeaponFullDef, szXAnimsLeftHanded[WEAP_ANIM_RAISE]), CSPFT_STRING },
|
{"raiseAnimL", offsetof(WeaponFullDef, szXAnimsLeftHanded[WEAP_ANIM_RAISE]), WFT_ANIM_NAME },
|
||||||
{"dropAnimL", offsetof(WeaponFullDef, szXAnimsLeftHanded[WEAP_ANIM_DROP]), CSPFT_STRING },
|
{"dropAnimL", offsetof(WeaponFullDef, szXAnimsLeftHanded[WEAP_ANIM_DROP]), WFT_ANIM_NAME },
|
||||||
{"firstRaiseAnimL", offsetof(WeaponFullDef, szXAnimsLeftHanded[WEAP_ANIM_FIRST_RAISE]), CSPFT_STRING },
|
{"firstRaiseAnimL", offsetof(WeaponFullDef, szXAnimsLeftHanded[WEAP_ANIM_FIRST_RAISE]), WFT_ANIM_NAME },
|
||||||
{"breachRaiseAnimL", offsetof(WeaponFullDef, szXAnimsLeftHanded[WEAP_ANIM_BREACH_RAISE]), CSPFT_STRING },
|
{"breachRaiseAnimL", offsetof(WeaponFullDef, szXAnimsLeftHanded[WEAP_ANIM_BREACH_RAISE]), WFT_ANIM_NAME },
|
||||||
{"altRaiseAnimL", offsetof(WeaponFullDef, szXAnimsLeftHanded[WEAP_ANIM_ALT_RAISE]), CSPFT_STRING },
|
{"altRaiseAnimL", offsetof(WeaponFullDef, szXAnimsLeftHanded[WEAP_ANIM_ALT_RAISE]), WFT_ANIM_NAME },
|
||||||
{"altDropAnimL", offsetof(WeaponFullDef, szXAnimsLeftHanded[WEAP_ANIM_ALT_DROP]), CSPFT_STRING },
|
{"altDropAnimL", offsetof(WeaponFullDef, szXAnimsLeftHanded[WEAP_ANIM_ALT_DROP]), WFT_ANIM_NAME },
|
||||||
{"quickRaiseAnimL", offsetof(WeaponFullDef, szXAnimsLeftHanded[WEAP_ANIM_QUICK_RAISE]), CSPFT_STRING },
|
{"quickRaiseAnimL", offsetof(WeaponFullDef, szXAnimsLeftHanded[WEAP_ANIM_QUICK_RAISE]), WFT_ANIM_NAME },
|
||||||
{"quickDropAnimL", offsetof(WeaponFullDef, szXAnimsLeftHanded[WEAP_ANIM_QUICK_DROP]), CSPFT_STRING },
|
{"quickDropAnimL", offsetof(WeaponFullDef, szXAnimsLeftHanded[WEAP_ANIM_QUICK_DROP]), WFT_ANIM_NAME },
|
||||||
{"emptyRaiseAnimL", offsetof(WeaponFullDef, szXAnimsLeftHanded[WEAP_ANIM_EMPTY_RAISE]), CSPFT_STRING },
|
{"emptyRaiseAnimL", offsetof(WeaponFullDef, szXAnimsLeftHanded[WEAP_ANIM_EMPTY_RAISE]), WFT_ANIM_NAME },
|
||||||
{"emptyDropAnimL", offsetof(WeaponFullDef, szXAnimsLeftHanded[WEAP_ANIM_EMPTY_DROP]), CSPFT_STRING },
|
{"emptyDropAnimL", offsetof(WeaponFullDef, szXAnimsLeftHanded[WEAP_ANIM_EMPTY_DROP]), WFT_ANIM_NAME },
|
||||||
{"sprintInAnimL", offsetof(WeaponFullDef, szXAnimsLeftHanded[WEAP_ANIM_SPRINT_IN]), CSPFT_STRING },
|
{"sprintInAnimL", offsetof(WeaponFullDef, szXAnimsLeftHanded[WEAP_ANIM_SPRINT_IN]), WFT_ANIM_NAME },
|
||||||
{"sprintLoopAnimL", offsetof(WeaponFullDef, szXAnimsLeftHanded[WEAP_ANIM_SPRINT_LOOP]), CSPFT_STRING },
|
{"sprintLoopAnimL", offsetof(WeaponFullDef, szXAnimsLeftHanded[WEAP_ANIM_SPRINT_LOOP]), WFT_ANIM_NAME },
|
||||||
{"sprintOutAnimL", offsetof(WeaponFullDef, szXAnimsLeftHanded[WEAP_ANIM_SPRINT_OUT]), CSPFT_STRING },
|
{"sprintOutAnimL", offsetof(WeaponFullDef, szXAnimsLeftHanded[WEAP_ANIM_SPRINT_OUT]), WFT_ANIM_NAME },
|
||||||
{"stunnedAnimStartL", offsetof(WeaponFullDef, szXAnimsLeftHanded[WEAP_ANIM_STUNNED_START]), CSPFT_STRING },
|
{"stunnedAnimStartL", offsetof(WeaponFullDef, szXAnimsLeftHanded[WEAP_ANIM_STUNNED_START]), WFT_ANIM_NAME },
|
||||||
{"stunnedAnimLoopL", offsetof(WeaponFullDef, szXAnimsLeftHanded[WEAP_ANIM_STUNNED_LOOP]), CSPFT_STRING },
|
{"stunnedAnimLoopL", offsetof(WeaponFullDef, szXAnimsLeftHanded[WEAP_ANIM_STUNNED_LOOP]), WFT_ANIM_NAME },
|
||||||
{"stunnedAnimEndL", offsetof(WeaponFullDef, szXAnimsLeftHanded[WEAP_ANIM_STUNNED_END]), CSPFT_STRING },
|
{"stunnedAnimEndL", offsetof(WeaponFullDef, szXAnimsLeftHanded[WEAP_ANIM_STUNNED_END]), WFT_ANIM_NAME },
|
||||||
{"nightVisionWearAnimL", offsetof(WeaponFullDef, szXAnimsLeftHanded[WEAP_ANIM_NIGHTVISION_WEAR]), CSPFT_STRING },
|
{"nightVisionWearAnimL", offsetof(WeaponFullDef, szXAnimsLeftHanded[WEAP_ANIM_NIGHTVISION_WEAR]), WFT_ANIM_NAME },
|
||||||
{"nightVisionRemoveAnimL", offsetof(WeaponFullDef, szXAnimsLeftHanded[WEAP_ANIM_NIGHTVISION_REMOVE]), CSPFT_STRING },
|
{"nightVisionRemoveAnimL", offsetof(WeaponFullDef, szXAnimsLeftHanded[WEAP_ANIM_NIGHTVISION_REMOVE]), WFT_ANIM_NAME },
|
||||||
{"adsFireAnimL", offsetof(WeaponFullDef, szXAnimsLeftHanded[WEAP_ANIM_ADS_FIRE]), CSPFT_STRING },
|
{"adsFireAnimL", offsetof(WeaponFullDef, szXAnimsLeftHanded[WEAP_ANIM_ADS_FIRE]), WFT_ANIM_NAME },
|
||||||
{"adsLastShotAnimL", offsetof(WeaponFullDef, szXAnimsLeftHanded[WEAP_ANIM_ADS_LASTSHOT]), CSPFT_STRING },
|
{"adsLastShotAnimL", offsetof(WeaponFullDef, szXAnimsLeftHanded[WEAP_ANIM_ADS_LASTSHOT]), WFT_ANIM_NAME },
|
||||||
{"adsRechamberAnimL", offsetof(WeaponFullDef, szXAnimsLeftHanded[WEAP_ANIM_ADS_RECHAMBER]), CSPFT_STRING },
|
{"adsRechamberAnimL", offsetof(WeaponFullDef, szXAnimsLeftHanded[WEAP_ANIM_ADS_RECHAMBER]), WFT_ANIM_NAME },
|
||||||
{"adsUpAnimL", offsetof(WeaponFullDef, szXAnimsLeftHanded[WEAP_ANIM_ADS_UP]), CSPFT_STRING },
|
{"adsUpAnimL", offsetof(WeaponFullDef, szXAnimsLeftHanded[WEAP_ANIM_ADS_UP]), WFT_ANIM_NAME },
|
||||||
{"adsDownAnimL", offsetof(WeaponFullDef, szXAnimsLeftHanded[WEAP_ANIM_ADS_DOWN]), CSPFT_STRING },
|
{"adsDownAnimL", offsetof(WeaponFullDef, szXAnimsLeftHanded[WEAP_ANIM_ADS_DOWN]), WFT_ANIM_NAME },
|
||||||
{"script", offsetof(WeaponFullDef, weapDef.szScript), CSPFT_STRING },
|
{"script", offsetof(WeaponFullDef, weapDef.szScript), CSPFT_STRING },
|
||||||
{"weaponType", offsetof(WeaponFullDef, weapDef.weapType), WFT_WEAPONTYPE },
|
{"weaponType", offsetof(WeaponFullDef, weapDef.weapType), WFT_WEAPONTYPE },
|
||||||
{"weaponClass", offsetof(WeaponFullDef, weapDef.weapClass), WFT_WEAPONCLASS },
|
{"weaponClass", offsetof(WeaponFullDef, weapDef.weapClass), WFT_WEAPONCLASS },
|
||||||
|
@ -1,13 +1,417 @@
|
|||||||
#include "AssetLoaderWeapon.h"
|
#include "AssetLoaderWeapon.h"
|
||||||
|
|
||||||
#include "Game/IW4/IW4.h"
|
#include "Game/IW4/IW4.h"
|
||||||
|
#include "Game/IW4/InfoString/EnumStrings.h"
|
||||||
|
#include "Game/IW4/InfoString/InfoStringToStructConverter.h"
|
||||||
|
#include "Game/IW4/InfoString/WeaponFields.h"
|
||||||
|
#include "Game/IW4/ObjConstantsIW4.h"
|
||||||
|
#include "InfoString/InfoString.h"
|
||||||
#include "ObjLoading.h"
|
#include "ObjLoading.h"
|
||||||
#include "Pool/GlobalAssetPool.h"
|
#include "Pool/GlobalAssetPool.h"
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
using namespace IW4;
|
using namespace IW4;
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
class InfoStringToWeaponConverter final : public InfoStringToStructConverter
|
||||||
|
{
|
||||||
|
bool ConvertHideTags(const cspField_t& field, const std::string& value)
|
||||||
|
{
|
||||||
|
std::vector<std::string> valueArray;
|
||||||
|
if (!ParseAsArray(value, valueArray))
|
||||||
|
{
|
||||||
|
std::cerr << "Failed to parse hide tags as array\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (valueArray.size() > std::extent_v<decltype(WeaponFullDef::hideTags)>)
|
||||||
|
{
|
||||||
|
std::cerr << "Cannot have more than " << std::extent_v<decltype(WeaponFullDef::hideTags)> << " hide tags!\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto* hideTags = reinterpret_cast<scr_string_t*>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset);
|
||||||
|
|
||||||
|
if (valueArray.size() < std::extent_v<decltype(WeaponFullDef::hideTags)>)
|
||||||
|
{
|
||||||
|
m_used_script_string_list.emplace(m_zone_script_strings.AddOrGetScriptString(nullptr));
|
||||||
|
}
|
||||||
|
|
||||||
|
auto currentHideTag = 0u;
|
||||||
|
for (; currentHideTag < valueArray.size(); currentHideTag++)
|
||||||
|
{
|
||||||
|
const auto& currentValue = valueArray[currentHideTag];
|
||||||
|
const auto scrString =
|
||||||
|
!currentValue.empty() ? m_zone_script_strings.AddOrGetScriptString(currentValue) : m_zone_script_strings.AddOrGetScriptString(nullptr);
|
||||||
|
hideTags[currentHideTag] = scrString;
|
||||||
|
m_used_script_string_list.emplace(scrString);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; currentHideTag < std::extent_v<decltype(WeaponFullDef::hideTags)>; currentHideTag++)
|
||||||
|
{
|
||||||
|
hideTags[currentHideTag] = m_zone_script_strings.GetScriptString(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
_NODISCARD bool ConvertBounceSounds(const cspField_t& field, const std::string& value) const
|
||||||
|
{
|
||||||
|
auto*** bounceSound = reinterpret_cast<const char***>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset);
|
||||||
|
if (value.empty())
|
||||||
|
{
|
||||||
|
*bounceSound = nullptr;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(std::extent_v<decltype(bounceSoundSuffixes)> == SURF_TYPE_NUM);
|
||||||
|
*bounceSound = static_cast<const char**>(m_memory->Alloc(sizeof(const char*) * SURF_TYPE_NUM));
|
||||||
|
for (auto i = 0u; i < SURF_TYPE_NUM; i++)
|
||||||
|
{
|
||||||
|
const auto currentBounceSound = value + bounceSoundSuffixes[i];
|
||||||
|
(*bounceSound)[i] = m_memory->Dup(currentBounceSound.c_str());
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
_NODISCARD bool ConvertNotetrackMap(const cspField_t& field, const std::string& value, const char* mapName, const size_t keyAndValueCount)
|
||||||
|
{
|
||||||
|
std::vector<std::pair<std::string, std::string>> pairs;
|
||||||
|
if (!ParseAsPairs(value, pairs))
|
||||||
|
{
|
||||||
|
std::cerr << "Failed to parse notetrack" << mapName << "map as pairs\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pairs.size() > std::extent_v<decltype(WeaponFullDef::notetrackSoundMapKeys)>)
|
||||||
|
{
|
||||||
|
std::cerr << "Cannot have more than " << std::extent_v<decltype(WeaponFullDef::notetrackSoundMapKeys)> << " notetrack" << mapName
|
||||||
|
<< "map entries!\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto* keys = reinterpret_cast<scr_string_t*>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset);
|
||||||
|
auto* values = &keys[keyAndValueCount];
|
||||||
|
auto currentEntryNum = 0u;
|
||||||
|
|
||||||
|
if (pairs.size() < keyAndValueCount)
|
||||||
|
{
|
||||||
|
m_used_script_string_list.emplace(m_zone_script_strings.AddOrGetScriptString(nullptr));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; currentEntryNum < pairs.size(); currentEntryNum++)
|
||||||
|
{
|
||||||
|
const auto& currentValue = pairs[currentEntryNum];
|
||||||
|
const auto keyScriptString = !currentValue.first.empty() ? m_zone_script_strings.AddOrGetScriptString(currentValue.first)
|
||||||
|
: m_zone_script_strings.AddOrGetScriptString(nullptr);
|
||||||
|
const auto valueScriptString = !currentValue.second.empty() ? m_zone_script_strings.AddOrGetScriptString(currentValue.second)
|
||||||
|
: m_zone_script_strings.AddOrGetScriptString(nullptr);
|
||||||
|
|
||||||
|
keys[currentEntryNum] = keyScriptString;
|
||||||
|
m_used_script_string_list.emplace(keyScriptString);
|
||||||
|
|
||||||
|
values[currentEntryNum] = valueScriptString;
|
||||||
|
m_used_script_string_list.emplace(valueScriptString);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; currentEntryNum < keyAndValueCount; currentEntryNum++)
|
||||||
|
{
|
||||||
|
const auto emptyScr = m_zone_script_strings.GetScriptString(nullptr);
|
||||||
|
keys[currentEntryNum] = emptyScr;
|
||||||
|
values[currentEntryNum] = emptyScr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ConvertAnimName(const cspField_t& field, const std::string& value)
|
||||||
|
{
|
||||||
|
if (ConvertString(value, field.iOffset))
|
||||||
|
{
|
||||||
|
if (!value.empty())
|
||||||
|
m_indirect_asset_references.emplace(m_loading_manager->LoadIndirectAssetReference(ASSET_TYPE_XANIMPARTS, value));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool ConvertExtensionField(const cspField_t& field, const std::string& value) override
|
||||||
|
{
|
||||||
|
switch (static_cast<weapFieldType_t>(field.iFieldType))
|
||||||
|
{
|
||||||
|
case WFT_WEAPONTYPE:
|
||||||
|
return ConvertEnumInt(value, field.iOffset, szWeapTypeNames, std::extent_v<decltype(szWeapTypeNames)>);
|
||||||
|
|
||||||
|
case WFT_WEAPONCLASS:
|
||||||
|
return ConvertEnumInt(value, field.iOffset, szWeapClassNames, std::extent_v<decltype(szWeapClassNames)>);
|
||||||
|
|
||||||
|
case WFT_OVERLAYRETICLE:
|
||||||
|
return ConvertEnumInt(value, field.iOffset, szWeapOverlayReticleNames, std::extent_v<decltype(szWeapOverlayReticleNames)>);
|
||||||
|
|
||||||
|
case WFT_PENETRATE_TYPE:
|
||||||
|
return ConvertEnumInt(value, field.iOffset, penetrateTypeNames, std::extent_v<decltype(penetrateTypeNames)>);
|
||||||
|
|
||||||
|
case WFT_IMPACT_TYPE:
|
||||||
|
return ConvertEnumInt(value, field.iOffset, impactTypeNames, std::extent_v<decltype(impactTypeNames)>);
|
||||||
|
|
||||||
|
case WFT_STANCE:
|
||||||
|
return ConvertEnumInt(value, field.iOffset, szWeapStanceNames, std::extent_v<decltype(szWeapStanceNames)>);
|
||||||
|
|
||||||
|
case WFT_PROJ_EXPLOSION:
|
||||||
|
return ConvertEnumInt(value, field.iOffset, szProjectileExplosionNames, std::extent_v<decltype(szProjectileExplosionNames)>);
|
||||||
|
|
||||||
|
case WFT_OFFHAND_CLASS:
|
||||||
|
return ConvertEnumInt(value, field.iOffset, offhandClassNames, std::extent_v<decltype(offhandClassNames)>);
|
||||||
|
|
||||||
|
case WFT_ANIMTYPE:
|
||||||
|
return ConvertEnumInt(value, field.iOffset, playerAnimTypeNames, std::extent_v<decltype(playerAnimTypeNames)>);
|
||||||
|
|
||||||
|
case WFT_ACTIVE_RETICLE_TYPE:
|
||||||
|
return ConvertEnumInt(value, field.iOffset, activeReticleNames, std::extent_v<decltype(activeReticleNames)>);
|
||||||
|
|
||||||
|
case WFT_GUIDED_MISSILE_TYPE:
|
||||||
|
return ConvertEnumInt(value, field.iOffset, guidedMissileNames, std::extent_v<decltype(guidedMissileNames)>);
|
||||||
|
|
||||||
|
case WFT_BOUNCE_SOUND:
|
||||||
|
return ConvertBounceSounds(field, value);
|
||||||
|
|
||||||
|
case WFT_STICKINESS:
|
||||||
|
return ConvertEnumInt(value, field.iOffset, stickinessNames, std::extent_v<decltype(stickinessNames)>);
|
||||||
|
|
||||||
|
case WFT_OVERLAYINTERFACE:
|
||||||
|
return ConvertEnumInt(value, field.iOffset, overlayInterfaceNames, std::extent_v<decltype(overlayInterfaceNames)>);
|
||||||
|
|
||||||
|
case WFT_INVENTORYTYPE:
|
||||||
|
return ConvertEnumInt(value, field.iOffset, szWeapInventoryTypeNames, std::extent_v<decltype(szWeapInventoryTypeNames)>);
|
||||||
|
|
||||||
|
case WFT_FIRETYPE:
|
||||||
|
return ConvertEnumInt(value, field.iOffset, szWeapFireTypeNames, std::extent_v<decltype(szWeapFireTypeNames)>);
|
||||||
|
|
||||||
|
case WFT_AMMOCOUNTER_CLIPTYPE:
|
||||||
|
return ConvertEnumInt(value, field.iOffset, ammoCounterClipNames, std::extent_v<decltype(ammoCounterClipNames)>);
|
||||||
|
|
||||||
|
case WFT_ICONRATIO_HUD:
|
||||||
|
case WFT_ICONRATIO_PICKUP:
|
||||||
|
case WFT_ICONRATIO_AMMOCOUNTER:
|
||||||
|
case WFT_ICONRATIO_KILL:
|
||||||
|
case WFT_ICONRATIO_DPAD:
|
||||||
|
return ConvertEnumInt(value, field.iOffset, weapIconRatioNames, std::extent_v<decltype(weapIconRatioNames)>);
|
||||||
|
|
||||||
|
case WFT_HIDETAGS:
|
||||||
|
return ConvertHideTags(field, value);
|
||||||
|
|
||||||
|
case WFT_NOTETRACKSOUNDMAP:
|
||||||
|
return ConvertNotetrackMap(field, value, "sound", std::extent_v<decltype(WeaponFullDef::notetrackSoundMapKeys)>);
|
||||||
|
|
||||||
|
case WFT_NOTETRACKRUMBLEMAP:
|
||||||
|
return ConvertNotetrackMap(field, value, "rumble", std::extent_v<decltype(WeaponFullDef::notetrackRumbleMapKeys)>);
|
||||||
|
|
||||||
|
case WFT_ANIM_NAME:
|
||||||
|
return ConvertAnimName(field, value);
|
||||||
|
|
||||||
|
default:
|
||||||
|
assert(false);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
InfoStringToWeaponConverter(const InfoString& infoString,
|
||||||
|
WeaponFullDef* weaponFullDef,
|
||||||
|
ZoneScriptStrings& zoneScriptStrings,
|
||||||
|
MemoryManager* memory,
|
||||||
|
IAssetLoadingManager* manager,
|
||||||
|
const cspField_t* fields,
|
||||||
|
const size_t fieldCount)
|
||||||
|
: InfoStringToStructConverter(infoString, weaponFullDef, zoneScriptStrings, memory, manager, fields, fieldCount)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void InitWeaponFullDef(WeaponFullDef* weapon)
|
||||||
|
{
|
||||||
|
weapon->weapCompleteDef.weapDef = &weapon->weapDef;
|
||||||
|
weapon->weapCompleteDef.hideTags = weapon->hideTags;
|
||||||
|
weapon->weapCompleteDef.szXAnims = weapon->szXAnims;
|
||||||
|
weapon->weapDef.gunXModel = weapon->gunXModel;
|
||||||
|
weapon->weapDef.szXAnimsRightHanded = weapon->szXAnimsRightHanded;
|
||||||
|
weapon->weapDef.szXAnimsLeftHanded = weapon->szXAnimsLeftHanded;
|
||||||
|
weapon->weapDef.notetrackSoundMapKeys = weapon->notetrackSoundMapKeys;
|
||||||
|
weapon->weapDef.notetrackSoundMapValues = weapon->notetrackSoundMapValues;
|
||||||
|
weapon->weapDef.notetrackRumbleMapKeys = weapon->notetrackRumbleMapKeys;
|
||||||
|
weapon->weapDef.notetrackRumbleMapValues = weapon->notetrackRumbleMapValues;
|
||||||
|
weapon->weapDef.worldModel = weapon->worldModel;
|
||||||
|
weapon->weapDef.parallelBounce = weapon->parallelBounce;
|
||||||
|
weapon->weapDef.perpendicularBounce = weapon->perpendicularBounce;
|
||||||
|
weapon->weapDef.locationDamageMultipliers = weapon->locationDamageMultipliers;
|
||||||
|
weapon->weapCompleteDef.szInternalName = "";
|
||||||
|
|
||||||
|
for (const auto& field : weapon_fields)
|
||||||
|
{
|
||||||
|
if (field.iFieldType != CSPFT_STRING)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
*reinterpret_cast<const char**>(reinterpret_cast<char*>(weapon) + field.iOffset) = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
snd_alias_list_name* CreateSoundAliasListName(const char* value, MemoryManager* memory)
|
||||||
|
{
|
||||||
|
auto* name = static_cast<snd_alias_list_name*>(memory->Alloc(sizeof(snd_alias_list_name)));
|
||||||
|
name->soundName = memory->Dup(value);
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CheckProjectileValues(const WeaponCompleteDef& weaponCompleteDef, const WeaponDef& weaponDef)
|
||||||
|
{
|
||||||
|
if (weaponDef.iProjectileSpeed <= 0)
|
||||||
|
std::cerr << std::format("Projectile speed for WeapType {} must be greater than 0.0", weaponCompleteDef.szDisplayName);
|
||||||
|
if (weaponDef.destabilizationCurvatureMax >= 1000000000.0f || weaponDef.destabilizationCurvatureMax < 0.0f)
|
||||||
|
std::cerr << std::format("Destabilization angle for for WeapType {} must be between 0 and 45 degrees", weaponCompleteDef.szDisplayName);
|
||||||
|
if (weaponDef.destabilizationRateTime < 0.0f)
|
||||||
|
std::cerr << std::format("Destabilization rate time for for WeapType {} must be non-negative", weaponCompleteDef.szDisplayName);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CheckTurretBarrelSpin(const WeaponCompleteDef& weaponCompleteDef, const WeaponDef& weaponDef)
|
||||||
|
{
|
||||||
|
if (weaponDef.weapClass != WEAPCLASS_TURRET)
|
||||||
|
std::cerr << std::format("Rotating barrel set for non-turret weapon {}.", weaponCompleteDef.szInternalName);
|
||||||
|
|
||||||
|
if (0.0f == weaponDef.turretBarrelSpinSpeed)
|
||||||
|
{
|
||||||
|
std::cerr << std::format(
|
||||||
|
"Rotating barrel spin speed '{}' is invalid for weapon {}.", weaponDef.turretBarrelSpinSpeed, weaponCompleteDef.szInternalName);
|
||||||
|
}
|
||||||
|
if (0.0f < weaponDef.turretOverheatUpRate && 0.0f >= weaponDef.turretOverheatDownRate)
|
||||||
|
{
|
||||||
|
std::cerr << std::format("Turret overheat Up rate is set, but the down rate '{}' is invalid for weapon {}.",
|
||||||
|
weaponDef.turretOverheatDownRate,
|
||||||
|
weaponCompleteDef.szInternalName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CheckThermalScope(const WeaponCompleteDef& weaponCompleteDef, const WeaponDef& weaponDef)
|
||||||
|
{
|
||||||
|
if (0.0f != weaponDef.fAdsZoomInFrac)
|
||||||
|
{
|
||||||
|
std::cerr << std::format("Weapon {} ({}) has thermal scope set. ADS Zoom In frac should be 0 to prevent zoom-in blur ({}).\n",
|
||||||
|
weaponCompleteDef.szInternalName,
|
||||||
|
weaponCompleteDef.szDisplayName,
|
||||||
|
weaponDef.fAdsZoomInFrac);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0.0f != weaponDef.fAdsZoomOutFrac)
|
||||||
|
{
|
||||||
|
std::cerr << std::format("Weapon {} ({}) has thermal scope set. ADS Zoom Out frac should be 0 to prevent zoom-out blur ({}).\n",
|
||||||
|
weaponCompleteDef.szInternalName,
|
||||||
|
weaponCompleteDef.szDisplayName,
|
||||||
|
weaponDef.fAdsZoomOutFrac);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CalculateWeaponFields(WeaponFullDef* weapon, MemoryManager* memory)
|
||||||
|
{
|
||||||
|
auto& weaponCompleteDef = weapon->weapCompleteDef;
|
||||||
|
auto& weaponDef = weapon->weapDef;
|
||||||
|
|
||||||
|
if (!weaponDef.viewLastShotEjectEffect)
|
||||||
|
weaponDef.viewLastShotEjectEffect = weaponDef.viewShellEjectEffect;
|
||||||
|
if (!weaponDef.worldLastShotEjectEffect)
|
||||||
|
weaponDef.worldLastShotEjectEffect = weaponDef.worldShellEjectEffect;
|
||||||
|
|
||||||
|
if (!weaponDef.raiseSound.name)
|
||||||
|
weaponDef.raiseSound.name = CreateSoundAliasListName("weap_raise", memory);
|
||||||
|
if (!weaponDef.putawaySound.name)
|
||||||
|
weaponDef.putawaySound.name = CreateSoundAliasListName("weap_putaway", memory);
|
||||||
|
if (!weaponDef.pickupSound.name)
|
||||||
|
weaponDef.pickupSound.name = CreateSoundAliasListName("weap_pickup", memory);
|
||||||
|
if (!weaponDef.ammoPickupSound.name)
|
||||||
|
weaponDef.ammoPickupSound.name = CreateSoundAliasListName("weap_ammo_pickup", memory);
|
||||||
|
if (!weaponDef.emptyFireSound.name)
|
||||||
|
weaponDef.emptyFireSound.name = CreateSoundAliasListName("weap_dryfire_smg_npc", memory);
|
||||||
|
|
||||||
|
if (weaponCompleteDef.iAdsTransInTime <= 0)
|
||||||
|
weaponDef.fOOPosAnimLength[0] = 0.0033333334f;
|
||||||
|
else
|
||||||
|
weaponDef.fOOPosAnimLength[0] = 1.0f / static_cast<float>(weaponCompleteDef.iAdsTransInTime);
|
||||||
|
|
||||||
|
if (weaponCompleteDef.iAdsTransOutTime <= 0)
|
||||||
|
weaponDef.fOOPosAnimLength[1] = 0.0020000001f;
|
||||||
|
else
|
||||||
|
weaponDef.fOOPosAnimLength[1] = 1.0f / static_cast<float>(weaponCompleteDef.iAdsTransOutTime);
|
||||||
|
|
||||||
|
if (weaponDef.fMaxDamageRange <= 0.0f)
|
||||||
|
weaponDef.fMaxDamageRange = 999999.0f;
|
||||||
|
if (weaponDef.fMinDamageRange <= 0.0f)
|
||||||
|
weaponDef.fMinDamageRange = 999999.12f;
|
||||||
|
|
||||||
|
if (weaponDef.enemyCrosshairRange > 15000.0f)
|
||||||
|
std::cerr << std::format("Enemy crosshair ranges should be less than {}\n", 15000.0f);
|
||||||
|
|
||||||
|
if (weaponDef.weapType == WEAPTYPE_PROJECTILE)
|
||||||
|
CheckProjectileValues(weaponCompleteDef, weaponDef);
|
||||||
|
|
||||||
|
if (weaponDef.turretBarrelSpinEnabled)
|
||||||
|
CheckTurretBarrelSpin(weaponCompleteDef, weaponDef);
|
||||||
|
|
||||||
|
if (weaponDef.thermalScope)
|
||||||
|
CheckThermalScope(weaponCompleteDef, weaponDef);
|
||||||
|
|
||||||
|
if (weaponDef.offhandClass && !weaponDef.bClipOnly)
|
||||||
|
{
|
||||||
|
std::cerr << std::format(
|
||||||
|
"Weapon {} ({}) is an offhand weapon but is not set to clip only, which is not supported since we can't reload the offhand slot.\n",
|
||||||
|
weaponCompleteDef.szInternalName,
|
||||||
|
weaponCompleteDef.szDisplayName);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (weaponDef.weapType == WEAPTYPE_BULLET)
|
||||||
|
{
|
||||||
|
if (weaponDef.bulletExplDmgMult <= 0.0f)
|
||||||
|
std::cerr << std::format("Detected invalid bulletExplDmgMult of '{}' for weapon '{}'; please update weapon settings.\n",
|
||||||
|
weaponDef.bulletExplDmgMult,
|
||||||
|
weaponCompleteDef.szInternalName);
|
||||||
|
if (weaponDef.bulletExplRadiusMult <= 0.0f)
|
||||||
|
std::cerr << std::format("Detected invalid bulletExplRadiusMult of '{}' for weapon '{}'; please update weapon settings.\n",
|
||||||
|
weaponDef.bulletExplRadiusMult,
|
||||||
|
weaponCompleteDef.szInternalName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LoadFromInfoString(const InfoString& infoString, const std::string& assetName, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone)
|
||||||
|
{
|
||||||
|
auto* weaponFullDef = memory->Create<WeaponFullDef>();
|
||||||
|
memset(weaponFullDef, 0, sizeof(WeaponFullDef));
|
||||||
|
InitWeaponFullDef(weaponFullDef);
|
||||||
|
|
||||||
|
InfoStringToWeaponConverter converter(
|
||||||
|
infoString, weaponFullDef, zone->m_script_strings, memory, manager, weapon_fields, std::extent_v<decltype(weapon_fields)>);
|
||||||
|
if (!converter.Convert())
|
||||||
|
{
|
||||||
|
std::cerr << "Failed to parse weapon: \"" << assetName << "\"\n";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
weaponFullDef->weapCompleteDef.szInternalName = memory->Dup(assetName.c_str());
|
||||||
|
|
||||||
|
CalculateWeaponFields(weaponFullDef, memory);
|
||||||
|
|
||||||
|
manager->AddAsset(ASSET_TYPE_WEAPON,
|
||||||
|
assetName,
|
||||||
|
&weaponFullDef->weapCompleteDef,
|
||||||
|
converter.GetDependencies(),
|
||||||
|
converter.GetUsedScriptStrings(),
|
||||||
|
converter.GetIndirectAssetReferences());
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
void* AssetLoaderWeapon::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
|
void* AssetLoaderWeapon::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
|
||||||
{
|
{
|
||||||
auto* weapon = memory->Create<WeaponCompleteDef>();
|
auto* weapon = memory->Create<WeaponCompleteDef>();
|
||||||
@ -15,3 +419,48 @@ void* AssetLoaderWeapon::CreateEmptyAsset(const std::string& assetName, MemoryMa
|
|||||||
weapon->szInternalName = memory->Dup(assetName.c_str());
|
weapon->szInternalName = memory->Dup(assetName.c_str());
|
||||||
return weapon;
|
return weapon;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool AssetLoaderWeapon::CanLoadFromGdt() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AssetLoaderWeapon::LoadFromGdt(
|
||||||
|
const std::string& assetName, IGdtQueryable* gdtQueryable, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const
|
||||||
|
{
|
||||||
|
const auto* gdtEntry = gdtQueryable->GetGdtEntryByGdfAndName(ObjConstants::GDF_FILENAME_WEAPON, assetName);
|
||||||
|
if (gdtEntry == nullptr)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
InfoString infoString;
|
||||||
|
if (!infoString.FromGdtProperties(*gdtEntry))
|
||||||
|
{
|
||||||
|
std::cerr << "Failed to read weapon gdt entry: \"" << assetName << "\"\n";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return LoadFromInfoString(infoString, assetName, memory, manager, zone);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AssetLoaderWeapon::CanLoadFromRaw() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AssetLoaderWeapon::LoadFromRaw(
|
||||||
|
const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const
|
||||||
|
{
|
||||||
|
const auto fileName = "weapons/" + assetName;
|
||||||
|
const auto file = searchPath->Open(fileName);
|
||||||
|
if (!file.IsOpen())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
InfoString infoString;
|
||||||
|
if (!infoString.FromStream(ObjConstants::INFO_STRING_PREFIX_WEAPON, *file.m_stream))
|
||||||
|
{
|
||||||
|
std::cerr << "Failed to read weapon raw file: \"" << fileName << "\"\n";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return LoadFromInfoString(infoString, assetName, memory, manager, zone);
|
||||||
|
}
|
||||||
|
@ -10,5 +10,11 @@ namespace IW4
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
|
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
|
||||||
|
_NODISCARD bool CanLoadFromGdt() const override;
|
||||||
|
bool LoadFromGdt(
|
||||||
|
const std::string& assetName, IGdtQueryable* gdtQueryable, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override;
|
||||||
|
_NODISCARD bool CanLoadFromRaw() const override;
|
||||||
|
bool
|
||||||
|
LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override;
|
||||||
};
|
};
|
||||||
} // namespace IW4
|
} // namespace IW4
|
||||||
|
@ -178,21 +178,16 @@ bool InfoStringToStructConverter::ConvertBaseField(const cspField_t& field, cons
|
|||||||
{
|
{
|
||||||
if (value.empty())
|
if (value.empty())
|
||||||
{
|
{
|
||||||
*reinterpret_cast<void**>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset) = nullptr;
|
reinterpret_cast<SndAliasCustom*>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset)->name = nullptr;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto* sound = m_loading_manager->LoadDependency(ASSET_TYPE_SOUND, value);
|
auto* name = static_cast<snd_alias_list_name*>(m_memory->Alloc(sizeof(snd_alias_list_name)));
|
||||||
|
name->soundName = m_memory->Dup(value.c_str());
|
||||||
|
|
||||||
if (sound == nullptr)
|
reinterpret_cast<SndAliasCustom*>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset)->name = name;
|
||||||
{
|
|
||||||
std::cout << "Failed to load sound asset \"" << value << "\"\n";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_dependencies.emplace(sound);
|
|
||||||
*reinterpret_cast<void**>(reinterpret_cast<uintptr_t>(m_structure) + field.iOffset) = sound->m_ptr;
|
|
||||||
|
|
||||||
|
m_indirect_asset_references.emplace(ASSET_TYPE_SOUND, value);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -199,6 +199,10 @@ namespace IW4
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case WFT_ANIM_NAME:
|
||||||
|
FillFromString(std::string(field.szName), field.iOffset);
|
||||||
|
break;
|
||||||
|
|
||||||
case WFT_NUM_FIELD_TYPES:
|
case WFT_NUM_FIELD_TYPES:
|
||||||
default:
|
default:
|
||||||
assert(false);
|
assert(false);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user