Add character screen model preview, item icons, stats panel, and fix targeting bugs

Enhanced the C-key character screen with a 3-column layout featuring a 3D
character model preview (with drag-to-rotate), item icons loaded from BLP
textures via ItemDisplayInfo.dbc, and a stats panel showing base + equipment
bonuses. Fixed selection circle clipping under terrain by adding a Z offset,
and corrected faction hostility logic that was wrongly marking hostile mobs
as friendly.
This commit is contained in:
Kelsi 2026-02-06 14:24:38 -08:00
parent 7128ea1417
commit 394e91cd9e
12 changed files with 738 additions and 53 deletions

View file

@ -72,8 +72,39 @@ public:
y = py;
z = pz;
orientation = o;
isMoving_ = false; // Instant position set cancels interpolation
}
// Movement interpolation (syncs entity position with renderer during movement)
void startMoveTo(float destX, float destY, float destZ, float destO, float durationSec) {
if (durationSec <= 0.0f) {
setPosition(destX, destY, destZ, destO);
return;
}
moveStartX_ = x; moveStartY_ = y; moveStartZ_ = z;
moveEndX_ = destX; moveEndY_ = destY; moveEndZ_ = destZ;
moveDuration_ = durationSec;
moveElapsed_ = 0.0f;
orientation = destO;
isMoving_ = true;
}
void updateMovement(float deltaTime) {
if (!isMoving_) return;
moveElapsed_ += deltaTime;
float t = moveElapsed_ / moveDuration_;
if (t >= 1.0f) {
x = moveEndX_; y = moveEndY_; z = moveEndZ_;
isMoving_ = false;
} else {
x = moveStartX_ + (moveEndX_ - moveStartX_) * t;
y = moveStartY_ + (moveEndY_ - moveStartY_) * t;
z = moveStartZ_ + (moveEndZ_ - moveStartZ_) * t;
}
}
bool isEntityMoving() const { return isMoving_; }
// Object type
ObjectType getType() const { return type; }
void setType(ObjectType t) { type = t; }
@ -108,6 +139,13 @@ protected:
// Update fields (dynamic values)
std::map<uint16_t, uint32_t> fields;
// Movement interpolation state
bool isMoving_ = false;
float moveStartX_ = 0, moveStartY_ = 0, moveStartZ_ = 0;
float moveEndX_ = 0, moveEndY_ = 0, moveEndZ_ = 0;
float moveDuration_ = 0;
float moveElapsed_ = 0;
};
/**
@ -162,6 +200,12 @@ public:
// Returns true if NPC has interaction flags (gossip/vendor/quest/trainer)
bool isInteractable() const { return npcFlags != 0; }
// Faction-based hostility
uint32_t getFactionTemplate() const { return factionTemplate; }
void setFactionTemplate(uint32_t f) { factionTemplate = f; }
bool isHostile() const { return hostile; }
void setHostile(bool h) { hostile = h; }
protected:
std::string name;
uint32_t health = 0;
@ -174,6 +218,8 @@ protected:
uint32_t displayId = 0;
uint32_t unitFlags = 0;
uint32_t npcFlags = 0;
uint32_t factionTemplate = 0;
bool hostile = false;
};
/**

View file

@ -294,6 +294,9 @@ public:
using CreatureDespawnCallback = std::function<void(uint64_t guid)>;
void setCreatureDespawnCallback(CreatureDespawnCallback cb) { creatureDespawnCallback_ = std::move(cb); }
// Faction hostility map (populated from FactionTemplate.dbc by Application)
void setFactionHostileMap(std::unordered_map<uint32_t, bool> map) { factionHostileMap_ = std::move(map); }
// Creature move callback (online mode - triggered by SMSG_MONSTER_MOVE)
// Parameters: guid, x, y, z (canonical), duration_ms (0 = instant)
using CreatureMoveCallback = std::function<void(uint64_t guid, float x, float y, float z, uint32_t durationMs)>;
@ -644,6 +647,13 @@ private:
// Quest log
std::vector<QuestLogEntry> questLog_;
// Faction hostility lookup (populated from FactionTemplate.dbc)
std::unordered_map<uint32_t, bool> factionHostileMap_;
bool isHostileFaction(uint32_t factionTemplateId) const {
auto it = factionHostileMap_.find(factionTemplateId);
return it != factionHostileMap_.end() ? it->second : true; // default hostile if unknown
}
// Vendor
bool vendorWindowOpen = false;
ListInventoryData currentVendorItems;

View file

@ -26,6 +26,8 @@ struct NpcSpawnDef {
float rotation; // radians around Z
float scale;
bool isCritter; // critters don't do humanoid emotes
uint32_t faction = 0; // faction template ID from creature_template
uint32_t npcFlags = 0; // NPC interaction flags from creature_template
};
struct NpcInstance {