"""Run the level-60 Arms plan through production Player::LearnTalent.""" from pathlib import Path import subprocess,tempfile root=Path(__file__).resolve().parents[2] s=(root/'src/server/game/Entities/Player/Player.cpp').read_text() a=s.index('bool Player::LearnTalent(');b=s.index('\nvoid Player::LearnPetTalent',a) # Native 4.3.4 Talent.dbc rows used by this plan; Impale depends on Deep Wounds 3/3. rows=[(10134,0,[84570,84571,84572]),(11163,0,[84579,84580]),(8176,1,[12834,12849,12867]),(8190,1,[29834,29838]), (10138,2,[56636,56637,56638]),(10741,2,[16493,16494]),(11418,3,[86655,12330]),(9662,3,[29836,29859]), (11223,3,[85730]),(10520,4,[84583,84587,84588]),(8208,4,[64976]),(8214,4,[29723,29725]),(8194,5,[46867,56611])] code=r''' #include "AdventureCombatPreparationPolicy.h" #include #include #include #include using uint32=uint32_t;using uint8=uint8_t;using int8=int8_t; #define TC_LOG_ERROR(...) ((void)0) #define TC_LOG_DEBUG(...) ((void)0) constexpr int MAX_TALENT_RANK=5,REQ_PRIMARY_TREE_TALENTS=31; struct TalentEntry{uint32 ID=0,TabID=746,TierID=0,ColumnIndex=0,SpellRank[5]={},PrereqTalent[3]={},PrereqRank[3]={};}; struct TalentTabEntry{uint32 ClassMask=1;}; struct Store{std::unordered_map rows;TalentEntry const* LookupEntry(uint32 id){auto i=rows.find(id);return i==rows.end()?nullptr:&i->second;}uint32 GetNumRows(){return 12000;}}sTalentStore; struct Tabs{TalentTabEntry tab;auto LookupEntry(uint32){return &tab;}}sTalentTabStore; struct Player{ uint32 points=26,mask=1;std::set spells; uint32 GetFreeTalentPoints(){return points;}uint32 getClassMask(){return mask;}uint32 GetPrimaryTalentTree(int){return 746;}int GetActiveSpec(){return 0;} bool HasSpell(uint32 spell){return spells.count(spell);} void LearnSpell(uint32 spell,bool){for(auto const& [id,t]:sTalentStore.rows)for(auto rank:t.SpellRank)if(rank==spell){for(auto old:t.SpellRank)spells.erase(old);}spells.insert(spell);} void AddTalent(uint32,int,bool){}void SetFreeTalentPoints(uint32 p){points=p;} bool LearnTalent(uint32,uint32); }; '''+s[a:b]+'\nint main(){\n' for id,tier,spells in rows: ranks=spells+[0]*(5-len(spells)) code+=f'sTalentStore.rows[{id}]={{{id},746,{tier},0,{{'+','.join(map(str,ranks))+'},{0,0,0},{0,0,0}};\n' code+=r''' sTalentStore.rows[10741].PrereqTalent[0]=8176;sTalentStore.rows[10741].PrereqRank[0]=2; Player p; assert(!p.LearnTalent(10741,0)); // cannot skip native dependency/tier gates unsigned spent=AdventureCombatPreparationPolicy::SpendArms60([&](uint32 id,uint32 rank){return p.LearnTalent(id,rank);},[&]{return p.points;}); assert(spent==26&&p.points==0); assert(p.HasSpell(84572)&&p.HasSpell(84580)&&p.HasSpell(12867)&&p.HasSpell(29838)); assert(p.HasSpell(56638)&&p.HasSpell(16494)&&p.HasSpell(46867)); assert(!p.HasSpell(46924)); // Bladestorm requires 31 points; level60 does not get it assert(AdventureCombatPreparationPolicy::SpendArms60([&](uint32 id,uint32 rank){return p.LearnTalent(id,rank);},[&]{return p.points;})==0); Player wrongClass;wrongClass.mask=128; assert(AdventureCombatPreparationPolicy::SpendArms60([&](uint32 id,uint32 rank){return wrongClass.LearnTalent(id,rank);},[&]{return wrongClass.points;})==0); assert(wrongClass.points==26&&wrongClass.spells.empty()); } ''' with tempfile.TemporaryDirectory() as tmp: src=Path(tmp)/'talents.cpp';exe=Path(tmp)/'talents';src.write_text(code) subprocess.run(['g++','-std=c++17','-I'+str(root/'src/server/game/World'),str(src),'-o',str(exe)],check=True) subprocess.run([str(exe)],check=True) print('Production talent learner: native tiers/dependencies/class gates, all 26 legal level60 points, no capstone bypass and repeat safety passed.')