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

@ -835,6 +835,11 @@ void GameHandler::update(float deltaTime) {
// Update combat text (Phase 2)
updateCombatText(deltaTime);
// Update entity movement interpolation (keeps targeting in sync with visuals)
for (auto& [guid, entity] : entityManager.getEntities()) {
entity->updateMovement(deltaTime);
}
// Single-player local combat
if (singlePlayerMode_) {
updateLocalCombat(deltaTime);
@ -2480,6 +2485,11 @@ void GameHandler::handleUpdateObject(network::Packet& packet) {
if (it != block.fields.end() && it->second != 0) {
auto unit = std::static_pointer_cast<Unit>(entity);
unit->setEntry(it->second);
// Set name from cache immediately if available
std::string cached = getCachedCreatureName(it->second);
if (!cached.empty()) {
unit->setName(cached);
}
queryCreatureInfo(it->second, block.guid);
}
}
@ -2493,6 +2503,7 @@ void GameHandler::handleUpdateObject(network::Packet& packet) {
case 25: unit->setPower(val); break;
case 32: unit->setMaxHealth(val); break;
case 33: unit->setMaxPower(val); break;
case 55: unit->setFactionTemplate(val); break; // UNIT_FIELD_FACTIONTEMPLATE
case 59: unit->setUnitFlags(val); break; // UNIT_FIELD_FLAGS
case 54: unit->setLevel(val); break;
case 67: unit->setDisplayId(val); break; // UNIT_FIELD_DISPLAYID
@ -2500,6 +2511,10 @@ void GameHandler::handleUpdateObject(network::Packet& packet) {
default: break;
}
}
// Determine hostility from faction template for online creatures
if (unit->getFactionTemplate() != 0) {
unit->setHostile(isHostileFaction(unit->getFactionTemplate()));
}
// Trigger creature spawn callback for units with displayId
if (block.objectType == ObjectType::UNIT && unit->getDisplayId() != 0) {
if (creatureSpawnCallback_) {
@ -2591,6 +2606,10 @@ void GameHandler::handleUpdateObject(network::Packet& packet) {
case 33: unit->setMaxPower(val); break;
case 59: unit->setUnitFlags(val); break; // UNIT_FIELD_FLAGS
case 54: unit->setLevel(val); break;
case 55: // UNIT_FIELD_FACTIONTEMPLATE
unit->setFactionTemplate(val);
unit->setHostile(isHostileFaction(val));
break;
case 82: unit->setNpcFlags(val); break; // UNIT_NPC_FLAGS
default: break;
}
@ -3191,8 +3210,9 @@ void GameHandler::handleMonsterMove(network::Packet& packet) {
}
}
// Set entity to destination for targeting/logic; renderer interpolates visually
entity->setPosition(destCanonical.x, destCanonical.y, destCanonical.z, orientation);
// Interpolate entity position alongside renderer (so targeting matches visual)
entity->startMoveTo(destCanonical.x, destCanonical.y, destCanonical.z,
orientation, data.duration / 1000.0f);
// Notify renderer to smoothly move the creature
if (creatureMoveCallback_) {