Fractured: Paragon core hooks, mod-paragon, mod-ale, Docker build cap
- Track mod-paragon and mod-ale (un-ignore modules in .gitignore). - Ship docker-compose.override.yml with CMAKE_EXTRA_OPTIONS for LuaJIT (mod-ale). - Dockerfile: CBUILD_PARALLEL default to limit OOM under Docker/WSL2. - Core: CLASS_PARAGON sticky combo points (DetachComboTarget), selection rebind, Spell::CheckPower rune path for multi-resource Paragon. - spell_dk_death_rune: IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_ABILITY) for Blood of the North / Reaping / DRM on Paragon. - Remove temporary Paragon CheckPower logging. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -25,6 +25,7 @@
|
||||
#include "CellImpl.h"
|
||||
#include "CharacterCache.h"
|
||||
#include "CharmInfo.h"
|
||||
#include "Config.h"
|
||||
#include "Chat.h"
|
||||
#include "ChatPackets.h"
|
||||
#include "ChatTextBuilder.h"
|
||||
@@ -13224,6 +13225,37 @@ void Unit::RestoreDisplayId()
|
||||
SetDisplayId(GetNativeDisplayId());
|
||||
}
|
||||
|
||||
// mod-paragon: returns true if this unit is a player whose combo-point pool
|
||||
// should persist across target swaps. Originally Paragon-only; widened to
|
||||
// cover the natively combo-point-using classes (Rogue, Druid) so the same
|
||||
// "stored CP pool" UX applies to them. Gate retains the existing config key
|
||||
// `Paragon.StickyComboPoints` for backward compatibility.
|
||||
static bool IsStickyComboPointsClass(Unit const* unit)
|
||||
{
|
||||
if (!unit || !unit->IsPlayer())
|
||||
return false;
|
||||
if (!sConfigMgr->GetOption<bool>("Paragon.StickyComboPoints", true))
|
||||
return false;
|
||||
uint8 cls = unit->ToPlayer()->getClass();
|
||||
return cls == CLASS_PARAGON || cls == CLASS_ROGUE || cls == CLASS_DRUID;
|
||||
}
|
||||
|
||||
uint8 Unit::GetComboPoints(Unit const* who) const
|
||||
{
|
||||
if (IsStickyComboPointsClass(this))
|
||||
return m_comboPoints;
|
||||
|
||||
return (who && m_comboTarget != who) ? 0 : m_comboPoints;
|
||||
}
|
||||
|
||||
uint8 Unit::GetComboPoints(ObjectGuid const& guid) const
|
||||
{
|
||||
if (IsStickyComboPointsClass(this))
|
||||
return m_comboPoints;
|
||||
|
||||
return (m_comboTarget && m_comboTarget->GetGUID() == guid) ? m_comboPoints : 0;
|
||||
}
|
||||
|
||||
void Unit::AddComboPoints(Unit* target, int8 count)
|
||||
{
|
||||
if (!count)
|
||||
@@ -13231,6 +13263,32 @@ void Unit::AddComboPoints(Unit* target, int8 count)
|
||||
return;
|
||||
}
|
||||
|
||||
if (IsStickyComboPointsClass(this))
|
||||
{
|
||||
if (target)
|
||||
{
|
||||
if (target != m_comboTarget)
|
||||
{
|
||||
if (m_comboTarget)
|
||||
m_comboTarget->RemoveComboPointHolder(this);
|
||||
|
||||
m_comboTarget = target;
|
||||
target->AddComboPointHolder(this);
|
||||
}
|
||||
}
|
||||
|
||||
m_comboPoints = std::max<int8>(std::min<int8>(m_comboPoints + count, 5), 0);
|
||||
|
||||
if (!m_comboPoints && m_comboTarget)
|
||||
{
|
||||
m_comboTarget->RemoveComboPointHolder(this);
|
||||
m_comboTarget = nullptr;
|
||||
}
|
||||
|
||||
SendComboPoints();
|
||||
return;
|
||||
}
|
||||
|
||||
if (target && target != m_comboTarget)
|
||||
{
|
||||
if (m_comboTarget)
|
||||
@@ -13250,6 +13308,20 @@ void Unit::AddComboPoints(Unit* target, int8 count)
|
||||
SendComboPoints();
|
||||
}
|
||||
|
||||
void Unit::RebindComboTarget(Unit* newTarget)
|
||||
{
|
||||
if (!newTarget || newTarget == m_comboTarget || m_comboPoints <= 0)
|
||||
return;
|
||||
|
||||
if (m_comboTarget)
|
||||
m_comboTarget->RemoveComboPointHolder(this);
|
||||
|
||||
m_comboTarget = newTarget;
|
||||
newTarget->AddComboPointHolder(this);
|
||||
|
||||
SendComboPoints();
|
||||
}
|
||||
|
||||
void Unit::ClearComboPoints()
|
||||
{
|
||||
if (!m_comboTarget)
|
||||
@@ -13267,6 +13339,26 @@ void Unit::ClearComboPoints()
|
||||
m_comboTarget = nullptr;
|
||||
}
|
||||
|
||||
void Unit::DetachComboTarget()
|
||||
{
|
||||
// mod-paragon: sticky-CP holder cleanup. Used when the target unit is
|
||||
// dying / despawning but we want to keep the holder's m_comboPoints
|
||||
// intact so they can finish on a fresh target. Pool re-binds via
|
||||
// Unit::RebindComboTarget on the next SetSelection (or via the next
|
||||
// AddComboPoints if the player generates more before tabbing).
|
||||
//
|
||||
// This intentionally does NOT touch SPELL_AURA_RETAIN_COMBO_POINTS and
|
||||
// does NOT call SendComboPoints — sticky-CP classes drive their target-
|
||||
// frame paint client-side (ComboFrame.lua's simulator for Paragon, the
|
||||
// sticky cache for Rogue/Druid), and a fake "binding to nullguid" packet
|
||||
// would just confuse the engine.
|
||||
if (m_comboTarget)
|
||||
{
|
||||
m_comboTarget->RemoveComboPointHolder(this);
|
||||
m_comboTarget = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void Unit::SendComboPoints()
|
||||
{
|
||||
if (m_cleanupDone)
|
||||
@@ -13309,7 +13401,21 @@ void Unit::ClearComboPointHolders()
|
||||
{
|
||||
while (!m_ComboPointHolders.empty())
|
||||
{
|
||||
(*m_ComboPointHolders.begin())->ClearComboPoints(); // this also removes it from m_comboPointHolders
|
||||
Unit* holder = *m_ComboPointHolders.begin();
|
||||
// mod-paragon: this is the *target* dying / despawning, iterating
|
||||
// every player who has CPs anchored to it. Stock behavior wipes the
|
||||
// holder's pool — that's the literal opposite of what
|
||||
// Paragon.StickyComboPoints promises. For sticky-CP classes
|
||||
// (Paragon / Rogue / Druid) detach the binding only and keep the
|
||||
// count, so the next finisher on a fresh target still has fuel.
|
||||
if (IsStickyComboPointsClass(holder))
|
||||
{
|
||||
holder->DetachComboTarget(); // also removes holder from m_ComboPointHolders
|
||||
}
|
||||
else
|
||||
{
|
||||
holder->ClearComboPoints(); // this also removes it from m_comboPointHolders
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user