"""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 #include #include 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')