mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-04-06 13:13:51 +00:00
Add animation_ids.hpp/cpp with all 452 WoW animation ID constants (anim::STAND, anim::RUN, anim::FIRE_BOW, ... anim::FLY_BACKWARDS, etc.), nameFromId() O(1) lookup, and flyVariant() compact 218-element ground→FLY_* resolver. Expand AnimationController into a full state machine with 20+ named states: spell cast (directed→omni→cast fallback chain, instant one-shot release), hit reactions (WOUND/CRIT/DODGE/BLOCK/SHIELD_BLOCK), stun, wounded idle, stealth animation substitution, loot, fishing channel, sit/sleep/kneel down→loop→up transitions, sheathe/unsheathe combat enter/exit, ranged weapons (BOW/GUN/CROSSBOW/THROWN with reload states), game object OPEN/CLOSE/DESTROY, vehicle enter/exit, mount flight directionals (FLY_LEFT/RIGHT/UP/DOWN/BACKWARDS), emote state variants, off-hand/pierce/dual-wield alternation, NPC birth/spawn/drown/rise, sprint aura override, totem idle, NPC greeting/farewell. Add spell_defines.hpp with SpellEffect (~45 constants) and SpellMissInfo (12 constants) namespaces; replace all magic numbers in spell_handler.cpp. Add GAMEOBJECT_BYTES_1 to update field table (all 4 expansion JSONs) and wire GameObjectStateCallback. Add DBC cross-validation on world entry. Expand tools/_ANIM_NAMES from ~35 to 452 entries in m2_viewer.py and asset_pipeline_gui.py. Add tests/test_animation_ids.cpp. Bug fixes included: - Stand state 1 was animating READY_2H(27) — fixed to SITTING(97) - Spell casts ended freeze-frame — add one-shot release animation - NPC 2H swing probe chain missing ATTACK_2H_LOOSE (polearm/staff) - Chair sits (states 2/4/5/6) incorrectly played floor-sit transition - STOP(3) used for all spell casts — replaced with model-aware chain
102 lines
4.2 KiB
C++
102 lines
4.2 KiB
C++
#pragma once
|
|
|
|
#include "game/character.hpp"
|
|
#include <string>
|
|
#include <vector>
|
|
#include <unordered_set>
|
|
#include <cstdint>
|
|
|
|
namespace wowee {
|
|
|
|
namespace rendering { class Renderer; }
|
|
namespace pipeline { class AssetManager; class DBCLayout; struct M2Model; }
|
|
namespace game { class GameHandler; }
|
|
|
|
namespace core {
|
|
|
|
class EntitySpawner;
|
|
|
|
// Default (bare) geoset IDs per equipment group.
|
|
// Each group's base is groupNumber * 100; variant 01 is typically bare/default.
|
|
constexpr uint16_t kGeosetDefaultConnector = 101; // Group 1: default hair connector
|
|
constexpr uint16_t kGeosetBareForearms = 401; // Group 4: no gloves
|
|
constexpr uint16_t kGeosetBareShins = 503; // Group 5: no boots
|
|
constexpr uint16_t kGeosetDefaultEars = 702; // Group 7: ears
|
|
constexpr uint16_t kGeosetBareSleeves = 801; // Group 8: no chest armor sleeves
|
|
constexpr uint16_t kGeosetDefaultKneepads = 902; // Group 9: kneepads
|
|
constexpr uint16_t kGeosetDefaultTabard = 1201; // Group 12: tabard base
|
|
constexpr uint16_t kGeosetBarePants = 1301; // Group 13: no leggings
|
|
constexpr uint16_t kGeosetNoCape = 1501; // Group 15: no cape
|
|
constexpr uint16_t kGeosetWithCape = 1502; // Group 15: with cape
|
|
constexpr uint16_t kGeosetBareFeet = 2002; // Group 20: bare feet
|
|
|
|
/// Resolved texture paths from CharSections.dbc for player character compositing.
|
|
struct PlayerTextureInfo {
|
|
std::string bodySkinPath;
|
|
std::string faceLowerPath;
|
|
std::string faceUpperPath;
|
|
std::string hairTexturePath;
|
|
std::vector<std::string> underwearPaths;
|
|
};
|
|
|
|
/// Handles player character visual appearance: skin compositing, geoset selection,
|
|
/// texture path lookups, and equipment weapon rendering.
|
|
class AppearanceComposer {
|
|
public:
|
|
AppearanceComposer(rendering::Renderer* renderer,
|
|
pipeline::AssetManager* assetManager,
|
|
game::GameHandler* gameHandler,
|
|
pipeline::DBCLayout* dbcLayout,
|
|
EntitySpawner* entitySpawner);
|
|
|
|
// Player model path resolution
|
|
std::string getPlayerModelPath(game::Race race, game::Gender gender) const;
|
|
|
|
// Resolve texture paths from CharSections.dbc and fill model texture slots.
|
|
// Call BEFORE charRenderer->loadModel().
|
|
PlayerTextureInfo resolvePlayerTextures(pipeline::M2Model& model,
|
|
game::Race race, game::Gender gender,
|
|
uint32_t appearanceBytes);
|
|
|
|
// Apply composited textures to loaded model instance.
|
|
// Call AFTER charRenderer->loadModel(). Saves skin state for re-compositing.
|
|
void compositePlayerSkin(uint32_t modelSlotId, const PlayerTextureInfo& texInfo);
|
|
|
|
// Build default active geosets for player character
|
|
std::unordered_set<uint16_t> buildDefaultPlayerGeosets(uint8_t raceId, uint8_t sexId,
|
|
uint8_t hairStyleId, uint8_t facialId);
|
|
|
|
// Equipment weapon loading (reads inventory, attaches weapon M2 models)
|
|
void loadEquippedWeapons();
|
|
|
|
// Weapon sheathe state
|
|
void setWeaponsSheathed(bool sheathed) { weaponsSheathed_ = sheathed; }
|
|
bool isWeaponsSheathed() const { return weaponsSheathed_; }
|
|
void toggleWeaponsSheathed() { weaponsSheathed_ = !weaponsSheathed_; }
|
|
|
|
// Saved skin state accessors (used by game_screen.cpp for equipment re-compositing)
|
|
const std::string& getBodySkinPath() const { return bodySkinPath_; }
|
|
const std::vector<std::string>& getUnderwearPaths() const { return underwearPaths_; }
|
|
uint32_t getSkinTextureSlotIndex() const { return skinTextureSlotIndex_; }
|
|
uint32_t getCloakTextureSlotIndex() const { return cloakTextureSlotIndex_; }
|
|
|
|
private:
|
|
bool loadWeaponM2(const std::string& m2Path, pipeline::M2Model& outModel);
|
|
|
|
rendering::Renderer* renderer_;
|
|
pipeline::AssetManager* assetManager_;
|
|
game::GameHandler* gameHandler_;
|
|
pipeline::DBCLayout* dbcLayout_;
|
|
EntitySpawner* entitySpawner_;
|
|
|
|
// Saved at spawn for skin re-compositing on equipment changes
|
|
std::string bodySkinPath_;
|
|
std::vector<std::string> underwearPaths_;
|
|
uint32_t skinTextureSlotIndex_ = 0;
|
|
uint32_t cloakTextureSlotIndex_ = 0;
|
|
|
|
bool weaponsSheathed_ = false;
|
|
};
|
|
|
|
} // namespace core
|
|
} // namespace wowee
|