46 lines
2.8 KiB
Python
46 lines
2.8 KiB
Python
"""Lock and Load correction clears effect 2: never scale an empty effect."""
|
|
from pathlib import Path
|
|
import subprocess,tempfile
|
|
root=Path(__file__).resolve().parents[2]
|
|
h=(root/'src/server/game/Spells/SpellInfo.h').read_text()
|
|
a=h.index(' SpellEffectInfo() :');b=h.index('{ }',a)+3;constructor=h[a:b]
|
|
s=(root/'src/server/game/Spells/Spell.cpp').read_text();a=s.index('SpellValue::SpellValue(');b=s.index('{',a);e=b+1;depth=1
|
|
while depth:depth+=(s[e]=='{')-(s[e]=='}');e+=1
|
|
code=r'''
|
|
#include <cassert>
|
|
#include <cstring>
|
|
#include <new>
|
|
using uint32=unsigned;constexpr int MAX_SPELL_EFFECTS=3,MECHANIC_NONE=0;
|
|
struct WorldObject{};
|
|
struct SpellEffectInfo{
|
|
void const*_spellInfo;unsigned _effIndex,Effect,ApplyAuraName,AuraPeriod,DieSides;
|
|
float RealPointsPerLevel,BasePoints,PointsPerComboPoint,Amplitude,DamageMultiplier,BonusMultiplier;
|
|
int MiscValue,MiscValueB,Mechanic;void const*TargetARadiusEntry;void const*TargetBRadiusEntry;
|
|
unsigned ChainTarget,ItemType,TriggerSpell;void*ImplicitTargetConditions;
|
|
struct{float Coefficient,Variance,ComboPointsCoefficient;}Scaling;
|
|
'''+constructor+r'''
|
|
bool IsEffect()const{return Effect!=0;}
|
|
int CalcBaseValue(WorldObject const*,void const*)const{assert(_spellInfo && IsEffect());return int(BasePoints);}
|
|
};
|
|
struct SpellInfo{SpellEffectInfo Effects[3];unsigned MaxAffectedTargets=0;};
|
|
struct SpellValue{int EffectBasePoints[3];unsigned CustomBasePointsMask,MaxAffectedTargets;float RadiusMod,AuraStackAmount,CriticalChance;SpellValue(SpellInfo const*,WorldObject const*);};
|
|
'''+s[a:e]+r'''
|
|
int main(){
|
|
alignas(SpellEffectInfo) unsigned char memory[sizeof(SpellEffectInfo)];memset(memory,0xA5,sizeof(memory));
|
|
auto empty=new(memory)SpellEffectInfo;
|
|
assert(!empty->_spellInfo && !empty->Effect && empty->Scaling.Coefficient==0 && empty->Scaling.Variance==0 && empty->Scaling.ComboPointsCoefficient==0);
|
|
SpellInfo spell;spell.Effects[0]._spellInfo=&spell;spell.Effects[0].Effect=1;spell.Effects[0].BasePoints=7;
|
|
spell.Effects[1]._spellInfo=&spell;spell.Effects[1].Effect=2;spell.Effects[1].BasePoints=12;
|
|
// Exact state produced by the 56342 native correction.
|
|
spell.Effects[2]=SpellEffectInfo();SpellValue value(&spell,nullptr);
|
|
assert(value.EffectBasePoints[0]==7 && value.EffectBasePoints[1]==12 && value.EffectBasePoints[2]==0);
|
|
spell.Effects[0]=SpellEffectInfo();spell.Effects[1]=SpellEffectInfo();SpellValue allEmpty(&spell,nullptr);
|
|
for(auto points:allEmpty.EffectBasePoints)assert(points==0);
|
|
}
|
|
'''
|
|
with tempfile.TemporaryDirectory() as d:
|
|
p=Path(d);(p/'test.cpp').write_text(code)
|
|
subprocess.run(['g++','-std=c++17',str(p/'test.cpp'),'-o',str(p/'test')],check=True)
|
|
subprocess.run([str(p/'test')],check=True)
|
|
print('Native empty spell effects: poisoned-memory scaling initialization, Lock and Load cleared slot, active effect values and all-empty spell values passed')
|