|
From: <xer...@us...> - 2026-07-23 02:45:52
|
Revision: 1677
http://sourceforge.net/p/seq/svn/1677
Author: xerxes00
Date: 2026-07-23 02:45:49 +0000 (Thu, 23 Jul 2026)
Log Message:
-----------
EQL: exact self mana from the stat-sync wide form; map stance/invocation ids
Mana (patch from Skik):
- Route the self mana pair from the stat-sync wide form (statUpdateEQL
case 2) into the new Player::setMana. Only EQL source with a real max,
and the only one that updates during regen. Stock OP_ManaChange stays
wired (cast-only, current-only).
- Keep the wire max in its own field (m_wireMaxMana, uint32) so
calcMaxMana recomputes and max-less ManaChange emits can't clobber it.
StatList prefers it over the high-water guess, so the displayed max
follows gear and buffs. Inert on live - nothing sets the wire max
there, so the guess behavior is unchanged.
Opcodes (ids from Skik):
- Map OP_Stance and OP_Invocation: Legends swappable stance / invocation
server echoes, 4 byte ability id. Mapped only, priority 0 / noHandler -
didn't take the handler half.
Thanks to Skik for both.
Modified Paths:
--------------
showeq/branches/showeqlegends/conf/zoneopcodes.xml
showeq/branches/showeqlegends/src/player.cpp
showeq/branches/showeqlegends/src/player.h
showeq/branches/showeqlegends/src/spawnshell.cpp
showeq/branches/showeqlegends/src/statlist.cpp
Modified: showeq/branches/showeqlegends/conf/zoneopcodes.xml
===================================================================
--- showeq/branches/showeqlegends/conf/zoneopcodes.xml 2026-07-22 23:28:54 UTC (rev 1676)
+++ showeq/branches/showeqlegends/conf/zoneopcodes.xml 2026-07-23 02:45:49 UTC (rev 1677)
@@ -1246,4 +1246,14 @@
<comment>SpellFadeCode</comment>
<payload dir="both" typename="spellFadedStruct" sizechecktype="none"/>
</opcode>
+ <opcode id="0fab" name="OP_Stance" priority="0" updated="07/14/26">
+ <priorityNote>noHandler</priorityNote>
+ <comment>EQ Legends swappable stance; server echo carries active ability id - 4 bytes</comment>
+ <payload dir="server" typename="uint8_t" sizechecktype="none"/>
+ </opcode>
+ <opcode id="3b12" name="OP_Invocation" priority="0" updated="07/14/26">
+ <priorityNote>noHandler</priorityNote>
+ <comment>EQ Legends swappable invocation; server echo carries active ability id - 4 bytes</comment>
+ <payload dir="server" typename="uint8_t" sizechecktype="none"/>
+ </opcode>
</seqopcodes>
Modified: showeq/branches/showeqlegends/src/player.cpp
===================================================================
--- showeq/branches/showeqlegends/src/player.cpp 2026-07-22 23:28:54 UTC (rev 1676)
+++ showeq/branches/showeqlegends/src/player.cpp 2026-07-23 02:45:49 UTC (rev 1677)
@@ -151,6 +151,7 @@
m_maxAGI = 0;
m_maxWIS = 0;
m_maxMana = 0;
+ m_wireMaxMana = 0; // EQL
m_maxHP = 0;
m_curHP = 0;
m_food = 0;
@@ -648,6 +649,25 @@
savePlayerState();
}
+void Player::setMana(uint32_t cur, uint32_t max)
+{
+ // EQL stat-sync wide form carries the player's exact current+max mana
+ // (gear+buff-inclusive). OP_ManaChange also rides the Legends wire, but it
+ // only fires on a cast and carries current with no max, so this is the only
+ // authoritative max and the only source that tracks regen. Hold the max
+ // separately as the wire max so a later calcMaxMana recompute (wear/remove
+ // item) can't clobber the displayed value.
+ m_mana = cur;
+ m_maxMana = max;
+ m_wireMaxMana = max;
+ m_validMana = true;
+
+ emit manaChanged(m_mana, m_maxMana);
+
+ if (showeq_params->savePlayerState)
+ savePlayerState();
+}
+
void Player::updateAltExp(const uint8_t* data)
{
const altExpUpdateStruct* altexp = (const altExpUpdateStruct*)data;
Modified: showeq/branches/showeqlegends/src/player.h
===================================================================
--- showeq/branches/showeqlegends/src/player.h 2026-07-22 23:28:54 UTC (rev 1676)
+++ showeq/branches/showeqlegends/src/player.h 2026-07-23 02:45:49 UTC (rev 1677)
@@ -81,6 +81,12 @@
void loadProfile(const playerProfileStruct& player);
void increaseSkill(const uint8_t* skilli);
void manaChange(const uint8_t* mana);
+ // EQL: exact current+max mana from the Legends stat channel
+ // (SpawnShell::statUpdateEQL wide form) - the only EQL source carrying a
+ // max (OP_ManaChange is cast-only and current-only). Stores the wire max
+ // separately (m_wireMaxMana) so a later calcMaxMana estimate can't clobber
+ // the display.
+ void setMana(uint32_t cur, uint32_t max);
void updateExp(const uint8_t* exp);
void updateAltExp(const uint8_t* altexp);
void updateLevel(const uint8_t* levelup);
@@ -144,6 +150,9 @@
uint8_t getMaxWIS() { return m_maxWIS; }
uint16_t getMaxMana() { return m_maxMana; }
uint16_t getMana() { return m_mana; }
+ // Exact gear+buff-inclusive max mana from the EQL stat-sync wide form;
+ // 0 on Live/Test (no wire max), where the display uses the estimate.
+ uint32_t wireMaxMana() const { return m_wireMaxMana; }
uint32_t getSpellBookSlot(uint32_t slotid) { return m_spellBookSlots[slotid]; }
uint32_t getCurrentExp() { return m_currentExp; }
@@ -242,6 +251,9 @@
uint16_t m_plusHP;
uint16_t m_maxMana;
+ // EQL: exact wire max mana; 0 => use estimate. uint32 not uint16 - the
+ // stat-sync wide form carries 64-bit values and setMana takes uint32.
+ uint32_t m_wireMaxMana = 0;
uint8_t m_maxSTR;
uint8_t m_maxSTA;
uint8_t m_maxCHA;
Modified: showeq/branches/showeqlegends/src/spawnshell.cpp
===================================================================
--- showeq/branches/showeqlegends/src/spawnshell.cpp 2026-07-22 23:28:54 UTC (rev 1676)
+++ showeq/branches/showeqlegends/src/spawnshell.cpp 2026-07-23 02:45:49 UTC (rev 1677)
@@ -1160,10 +1160,12 @@
// This decoder only PARSES the Legends container; it emits a stock
// hpNpcUpdateStruct into the stock display paths (SpawnShell::updateNpcHP
// for spawns, Player::updateNpcHP for self - each does its own spawnId
- // routing, exactly as stock wires OP_HPUpdate to both). Mana rides stock
- // OP_ManaChange; self endurance goes to Player::updateEnduranceEQL (Stam
- // row). Food/water do NOT ride this channel (verified with destroyed-food
- // + out-of-food captures).
+ // routing, exactly as stock wires OP_HPUpdate to both). Self mana (exact
+ // cur/max, gear+buff-inclusive) goes to Player::setMana; stock OP_ManaChange
+ // still fires alongside on casts (current only, no max) and stays wired.
+ // Self endurance goes to Player::updateEnduranceEQL (Stam row). Food/water
+ // do NOT ride this channel (verified with destroyed-food + out-of-food
+ // captures).
if (dir != DIR_Server)
return;
@@ -1227,7 +1229,11 @@
m_player->updateNpcHP((const uint8_t*)&hp);
break;
}
- case 2: // mana - the player's mana rides stock OP_ManaChange
+ case 2: // mana - EQL carries the player's exact cur/max here; OP_ManaChange
+ // fires only on a cast and carries no max, so this is the only
+ // source of a real max for the display (vs the calcMaxMana estimate).
+ if (wide && uint16_t(spawnId) == m_player->id())
+ m_player->setMana(uint32_t(cur), uint32_t(max));
break;
case 3: // endurance - self only, onto the Stam row
if (uint16_t(spawnId) == m_player->id())
Modified: showeq/branches/showeqlegends/src/statlist.cpp
===================================================================
--- showeq/branches/showeqlegends/src/statlist.cpp 2026-07-22 23:28:54 UTC (rev 1676)
+++ showeq/branches/showeqlegends/src/statlist.cpp 2026-07-23 02:45:49 UTC (rev 1677)
@@ -178,12 +178,21 @@
m_statList[LIST_MANA]->setText (1, buf);
- if (val > m_guessMaxMana) {
- m_guessMaxMana = val;
+ // EQL supplies the exact gear+buff-inclusive max mana on the wire
+ // (Player::setMana). When present it is authoritative and tracks
+ // equip/unequip and buffs, so use it directly instead of the high-water
+ // estimate, which only ever climbs and drifts a point above the true max.
+ uint32_t wireMax = m_player->wireMaxMana();
+ if (wireMax > 0) {
+ m_guessMaxMana = wireMax;
+ } else {
+ if (val > m_guessMaxMana) {
+ m_guessMaxMana = val;
+ }
+ if (max > m_guessMaxMana) {
+ m_guessMaxMana = max;
+ }
}
- if (max > m_guessMaxMana) {
- m_guessMaxMana = max;
- }
if (m_guessMaxMana < 0)
m_guessMaxMana = 0;
@@ -288,11 +297,18 @@
{
valStr = QString::number(value);
- // attempt to calculate the maximum amount of mana
- if (value > m_guessMaxMana)
- m_guessMaxMana = value;
- if (max > m_guessMaxMana)
- m_guessMaxMana = max;
+ // attempt to calculate the maximum amount of mana; EQL provides the
+ // exact wire max (Player::setMana) which is authoritative when present.
+ uint32_t wireMax = m_player->wireMaxMana();
+ if (wireMax > 0)
+ m_guessMaxMana = wireMax;
+ else
+ {
+ if (value > m_guessMaxMana)
+ m_guessMaxMana = value;
+ if (max > m_guessMaxMana)
+ m_guessMaxMana = max;
+ }
if (m_guessMaxMana < 0)
m_guessMaxMana = 0;
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|