mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2025-04-20 08:05:45 +00:00
chore: dump iw5 weapon anim overrides
This commit is contained in:
parent
a27241701b
commit
8554939c91
@ -116,6 +116,7 @@ namespace IW5
|
||||
// Custom
|
||||
WFT_ANIM_NAME,
|
||||
WFT_ATTACHMENT,
|
||||
WFT_ANIM_OVERRIDES,
|
||||
|
||||
WFT_NUM_FIELD_TYPES,
|
||||
};
|
||||
|
@ -3383,7 +3383,7 @@ namespace IW5
|
||||
MISSILE_GUIDANCE_COUNT
|
||||
};
|
||||
|
||||
enum weapAnimFiles_t
|
||||
enum weapAnimFiles_t : unsigned int
|
||||
{
|
||||
WEAP_ANIM_ROOT = 0x0,
|
||||
WEAP_ANIM_IDLE = 0x1,
|
||||
@ -3428,7 +3428,7 @@ namespace IW5
|
||||
WEAP_ANIM_ADS_DOWN = 0x28,
|
||||
WEAP_ALT_ANIM_ADJUST = 0x29,
|
||||
|
||||
NUM_WEAP_ANIMS
|
||||
WEAP_ANIM_COUNT
|
||||
};
|
||||
|
||||
enum hitLocation_t
|
||||
@ -3895,13 +3895,30 @@ namespace IW5
|
||||
XModel* stowOffsetModel;
|
||||
};
|
||||
|
||||
union WeaponAttachmentCombination
|
||||
{
|
||||
struct
|
||||
{
|
||||
// Specifies the index as a number
|
||||
// since there can only be one scope
|
||||
unsigned short scope : 3;
|
||||
// Specifies the index as a number
|
||||
// since there can only be one under barrel
|
||||
unsigned short underBarrel : 2;
|
||||
// Specifies all other attachments as a bit array
|
||||
unsigned short other : 4;
|
||||
};
|
||||
|
||||
unsigned short fields;
|
||||
};
|
||||
|
||||
struct AnimOverrideEntry
|
||||
{
|
||||
unsigned short attachment1;
|
||||
unsigned short attachment2;
|
||||
WeaponAttachmentCombination attachment1;
|
||||
WeaponAttachmentCombination attachment2;
|
||||
const char* overrideAnim;
|
||||
const char* altmodeAnim;
|
||||
unsigned int animTreeType;
|
||||
weapAnimFiles_t animTreeType;
|
||||
int animTime;
|
||||
int altTime;
|
||||
};
|
||||
|
@ -4,7 +4,6 @@
|
||||
namespace IW5
|
||||
{
|
||||
// WeaponCompleteDef:
|
||||
// TODO: animOverrides
|
||||
// TODO: soundOverrides
|
||||
// TODO: fxOverrides
|
||||
// TODO: reloadOverrides
|
||||
@ -734,6 +733,7 @@ namespace IW5
|
||||
{"missileConeSoundCrossfadeTopSize", offsetof(WeaponFullDef, weapDef.missileConeSoundCrossfadeTopSize), CSPFT_FLOAT },
|
||||
{"missileConeSoundCrossfadeBottomSize", offsetof(WeaponFullDef, weapDef.missileConeSoundCrossfadeBottomSize), CSPFT_FLOAT },
|
||||
{"attachments", offsetof(WeaponFullDef, scopes), WFT_ATTACHMENT },
|
||||
{"animOverrides", offsetof(WeaponFullDef, weapCompleteDef.animOverrides), WFT_ANIM_OVERRIDES },
|
||||
};
|
||||
|
||||
inline const char* szWeapTypeNames[]{
|
||||
@ -914,4 +914,15 @@ namespace IW5
|
||||
"_gravel", "_ice", "_metal", "_mud", "_paper", "_plaster", "_rock", "_sand", "_snow", "_water", "_wood",
|
||||
"_asphalt", "_ceramic", "_plastic", "_rubber", "_cushion", "_fruit", "_painted_metal", "_riot_shield", "_slush",
|
||||
};
|
||||
static_assert(std::extent_v<decltype(bounceSoundSuffixes)> == SURF_TYPE_COUNT);
|
||||
|
||||
inline const char* weapAnimFilesNames[]{
|
||||
"root", "idle", "empty_idle", "fire", "hold_fire", "lastshot", "rechamber", "melee",
|
||||
"melee_charge", "reload", "reload_empty", "reload_start", "reload_end", "raise", "first_raise", "breach_raise",
|
||||
"drop", "alt_raise", "alt_drop", "quick_raise", "quick_drop", "empty_raise", "empty_drop", "sprint_in",
|
||||
"sprint_loop", "sprint_out", "stunned_start", "stunned_loop", "stunned_end", "detonate", "nightvision_wear", "nightvision_remove",
|
||||
"ads_fire", "ads_lastshot", "ads_rechamber", "blast_front", "blast_right", "blast_back", "blast_left", "ads_up",
|
||||
"ads_down", "alt_adjust",
|
||||
};
|
||||
static_assert(std::extent_v<decltype(weapAnimFilesNames)> == WEAP_ANIM_COUNT);
|
||||
} // namespace IW5
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "Game/IW5/InfoString/WeaponFields.h"
|
||||
#include "Game/IW5/ObjConstantsIW5.h"
|
||||
|
||||
#include <bit>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <sstream>
|
||||
@ -216,6 +217,10 @@ namespace IW5
|
||||
FillFromAttachments(std::string(field.szName));
|
||||
break;
|
||||
|
||||
case WFT_ANIM_OVERRIDES:
|
||||
FillFromAnimOverrides(std::string(field.szName));
|
||||
break;
|
||||
|
||||
case WFT_NUM_FIELD_TYPES:
|
||||
default:
|
||||
assert(false);
|
||||
@ -271,6 +276,87 @@ namespace IW5
|
||||
m_info_string.SetValueForKey(key, ss.str());
|
||||
}
|
||||
|
||||
[[nodiscard]] std::string GetNameForSingleWeaponAttachment(const WeaponAttachmentCombination& combination) const
|
||||
{
|
||||
// Only one attachment type can be set
|
||||
assert(combination.scope == 0 || (combination.underBarrel == 0 && combination.other == 0));
|
||||
assert(combination.underBarrel == 0 || (combination.scope == 0 && combination.other == 0));
|
||||
assert(combination.other == 0 || (combination.scope == 0 && std::popcount(combination.other) == 1));
|
||||
|
||||
if (combination.scope > 0 && m_weapon->weapCompleteDef.scopes)
|
||||
{
|
||||
const auto attachment = m_weapon->weapCompleteDef.scopes[combination.scope - 1];
|
||||
if (attachment && attachment->szInternalName)
|
||||
return attachment->szInternalName;
|
||||
}
|
||||
else if (combination.underBarrel > 0 && m_weapon->weapCompleteDef.underBarrels)
|
||||
{
|
||||
const auto attachment = m_weapon->weapCompleteDef.underBarrels[combination.underBarrel - 1];
|
||||
if (attachment && attachment->szInternalName)
|
||||
return attachment->szInternalName;
|
||||
}
|
||||
else if (combination.other > 0 && m_weapon->weapCompleteDef.others)
|
||||
{
|
||||
const auto attachment = m_weapon->weapCompleteDef.others[std::countr_zero(combination.other)];
|
||||
if (attachment && attachment->szInternalName)
|
||||
return attachment->szInternalName;
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
void FillFromAnimOverrides(const std::string& key)
|
||||
{
|
||||
std::stringstream ss;
|
||||
bool first = true;
|
||||
|
||||
for (auto i = 0u; i < m_weapon->weapCompleteDef.numAnimOverrides; i++)
|
||||
{
|
||||
const auto& animOverride = m_weapon->weapCompleteDef.animOverrides[i];
|
||||
|
||||
if (!first)
|
||||
ss << "\n";
|
||||
else
|
||||
first = false;
|
||||
|
||||
assert(animOverride.attachment1.fields);
|
||||
assert(animOverride.animTreeType < WEAP_ANIM_COUNT);
|
||||
|
||||
if (animOverride.attachment1.fields)
|
||||
ss << GetNameForSingleWeaponAttachment(animOverride.attachment1);
|
||||
else
|
||||
ss << "none";
|
||||
|
||||
ss << ' ';
|
||||
|
||||
if (animOverride.attachment2.fields)
|
||||
ss << GetNameForSingleWeaponAttachment(animOverride.attachment2);
|
||||
else
|
||||
ss << "none";
|
||||
|
||||
ss << ' ';
|
||||
|
||||
if (animOverride.animTreeType < WEAP_ANIM_COUNT)
|
||||
ss << weapAnimFilesNames[animOverride.animTreeType] << ' ';
|
||||
|
||||
if (animOverride.overrideAnim && animOverride.overrideAnim[0])
|
||||
ss << animOverride.overrideAnim;
|
||||
else
|
||||
ss << "none";
|
||||
|
||||
ss << ' ';
|
||||
|
||||
if (animOverride.altmodeAnim && animOverride.altmodeAnim[0])
|
||||
ss << animOverride.altmodeAnim;
|
||||
else
|
||||
ss << "none";
|
||||
|
||||
ss << ' ' << animOverride.animTime << ' ' << animOverride.altTime;
|
||||
}
|
||||
|
||||
m_info_string.SetValueForKey(key, ss.str());
|
||||
}
|
||||
|
||||
const WeaponFullDef* m_weapon;
|
||||
};
|
||||
} // namespace IW5
|
||||
@ -293,8 +379,8 @@ void AssetDumperWeapon::CopyToFullDef(const WeaponCompleteDef* weapon, WeaponFul
|
||||
|
||||
if (weapon->szXAnims)
|
||||
{
|
||||
static_assert(std::extent_v<decltype(WeaponFullDef::szXAnims)> == NUM_WEAP_ANIMS);
|
||||
memcpy(fullDef->szXAnims, weapon->szXAnims, sizeof(void*) * NUM_WEAP_ANIMS);
|
||||
static_assert(std::extent_v<decltype(WeaponFullDef::szXAnims)> == WEAP_ANIM_COUNT);
|
||||
memcpy(fullDef->szXAnims, weapon->szXAnims, sizeof(void*) * WEAP_ANIM_COUNT);
|
||||
fullDef->weapCompleteDef.szXAnims = fullDef->szXAnims;
|
||||
}
|
||||
|
||||
@ -306,15 +392,15 @@ void AssetDumperWeapon::CopyToFullDef(const WeaponCompleteDef* weapon, WeaponFul
|
||||
|
||||
if (fullDef->weapDef.szXAnimsRightHanded)
|
||||
{
|
||||
static_assert(std::extent_v<decltype(WeaponFullDef::szXAnimsRightHanded)> == NUM_WEAP_ANIMS);
|
||||
memcpy(fullDef->szXAnimsRightHanded, fullDef->weapDef.szXAnimsRightHanded, sizeof(void*) * NUM_WEAP_ANIMS);
|
||||
static_assert(std::extent_v<decltype(WeaponFullDef::szXAnimsRightHanded)> == WEAP_ANIM_COUNT);
|
||||
memcpy(fullDef->szXAnimsRightHanded, fullDef->weapDef.szXAnimsRightHanded, sizeof(void*) * WEAP_ANIM_COUNT);
|
||||
fullDef->weapDef.szXAnimsRightHanded = fullDef->szXAnimsRightHanded;
|
||||
}
|
||||
|
||||
if (fullDef->weapDef.szXAnimsLeftHanded)
|
||||
{
|
||||
static_assert(std::extent_v<decltype(WeaponFullDef::szXAnimsLeftHanded)> == NUM_WEAP_ANIMS);
|
||||
memcpy(fullDef->szXAnimsLeftHanded, fullDef->weapDef.szXAnimsLeftHanded, sizeof(void*) * NUM_WEAP_ANIMS);
|
||||
static_assert(std::extent_v<decltype(WeaponFullDef::szXAnimsLeftHanded)> == WEAP_ANIM_COUNT);
|
||||
memcpy(fullDef->szXAnimsLeftHanded, fullDef->weapDef.szXAnimsLeftHanded, sizeof(void*) * WEAP_ANIM_COUNT);
|
||||
fullDef->weapDef.szXAnimsLeftHanded = fullDef->szXAnimsLeftHanded;
|
||||
}
|
||||
|
||||
|
@ -19,7 +19,7 @@ set count others 4;
|
||||
set string szXAnims;
|
||||
set assetref szXAnims ASSET_TYPE_XANIMPARTS;
|
||||
set reusable szXAnims;
|
||||
set count szXAnims NUM_WEAP_ANIMS;
|
||||
set count szXAnims WEAP_ANIM_COUNT;
|
||||
set reusable animOverrides;
|
||||
set count animOverrides numAnimOverrides;
|
||||
set reusable soundOverrides;
|
||||
@ -59,11 +59,11 @@ set count gunXModel 16;
|
||||
set reusable szXAnimsRightHanded;
|
||||
set string szXAnimsRightHanded;
|
||||
set assetref szXAnimsRightHanded ASSET_TYPE_XANIMPARTS;
|
||||
set count szXAnimsRightHanded NUM_WEAP_ANIMS;
|
||||
set count szXAnimsRightHanded WEAP_ANIM_COUNT;
|
||||
set reusable szXAnimsLeftHanded;
|
||||
set string szXAnimsLeftHanded;
|
||||
set assetref szXAnimsLeftHanded ASSET_TYPE_XANIMPARTS;
|
||||
set count szXAnimsLeftHanded NUM_WEAP_ANIMS;
|
||||
set count szXAnimsLeftHanded WEAP_ANIM_COUNT;
|
||||
set string szModeName;
|
||||
set reusable notetrackSoundMapKeys;
|
||||
set scriptstring notetrackSoundMapKeys;
|
||||
|
Loading…
x
Reference in New Issue
Block a user