Files
Viano-Core/tests/clientless/test_native_skill_slot.py
T
Nico 49712aadfe
GCC PCH / build (push) Waiting to run
clang PCH / build (push) Canceled after 0s
Improve AdventureBot travel recovery and destination eligibility
2026-10-29 11:10:27 +01:00

64 lines
3.2 KiB
Python

"""Exercise the actual free-slot branch used by Player::SetSkill."""
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('uint16 skillSlot = PLAYER_MAX_SKILLS;',s.index('void Player::SetSkill('))
b=s.index(' if (skillEntry->CategoryID',a)
code=r'''
#include <array>
#include <cassert>
using uint16=unsigned short;using uint32=unsigned;
constexpr unsigned PLAYER_MAX_SKILLS=128,PLAYER_SKILL_LINEID_0=0;
#define TC_LOG_ERROR(...) ((void)0)
std::array<unsigned,128> fields;
unsigned GetUInt16Value(unsigned f,unsigned offset){return fields[2*f+offset];}
int selected=-1;
void add(){
'''+s[a:b]+r'''
selected=skillSlot;
}
int main(){fields.fill(1);fields[0]=0;add();assert(selected==0);
fields.fill(1);fields[127]=0;add();assert(selected==127);
fields.fill(1);selected=-1;add();assert(selected==-1);}
'''
with tempfile.TemporaryDirectory()as d:
p=Path(d);(p/'test.cpp').write_text(code)
subprocess.run(['c++','-std=c++17',str(p/'test.cpp'),'-o',str(p/'test')],check=True)
subprocess.run([str(p/'test')],check=True)
print('Native riding/profession allocation accepts slot zero and last slot, rejects a full skill array')
# Exercise recursive rewarded-spell learning on an initialized zero-rank placeholder.
a=s.index(' // update step',s.index('void Player::SetSkill('))
b=s.index(' // archaeology handling',a)
activation=r'''
#include <map>
#include <cassert>
using uint16=unsigned short;using uint32=unsigned;
enum {SKILL_UNCHANGED,SKILL_NEW,SKILL_CHANGED,SKILL_DELETED};
enum {SKILL_CATEGORY_PROFESSION=11,SKILL_RIDING=762,PLAYER_PROFESSION_SKILL_LINE_1=3,
ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL=4,ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LEVEL=5};
struct State {unsigned pos=0,uState=SKILL_UNCHANGED;};
struct Entry{unsigned CategoryID=0;} entry;
std::map<unsigned,State> states{{762,{}}};unsigned value=0;bool recursing=false;
void SetSkillStep(unsigned,unsigned){}void SetSkillRank(unsigned,unsigned v){value=v;}
void SetSkillMaxRank(unsigned,unsigned){}unsigned GetUInt32Value(unsigned){return 0;}
void SetUInt32Value(unsigned,unsigned){}void refreshSkillBonusAuras(){}
void UpdateSkillEnchantments(unsigned,unsigned,unsigned){}void UpdateMountCapability(){}
void UpdateAchievementCriteria(unsigned,unsigned){}
void activate(unsigned newVal);
void LearnSkillRewardedSpells(unsigned,unsigned v){if(!recursing){recursing=true;activate(v);recursing=false;}}
void activate(unsigned newVal){unsigned currVal=value,step=3,maxVal=225,id=762;
auto itr=states.find(id);auto skillEntry=&entry;
'''+s[a:b]+r'''
}
int main(){activate(225);assert(states[762].uState==SKILL_NEW);
states[762].uState=SKILL_UNCHANGED;activate(300);assert(states[762].uState==SKILL_CHANGED);
states[762].uState=SKILL_DELETED;value=0;activate(225);assert(states[762].uState==SKILL_CHANGED);}
'''
with tempfile.TemporaryDirectory() as d:
p=Path(d);(p/'activation.cpp').write_text(activation)
subprocess.run(['c++','-std=c++17',str(p/'activation.cpp'),'-o',str(p/'activation')],check=True)
subprocess.run([str(p/'activation')],check=True)
print('Native recursive skill activation preserves INSERT for new placeholders and UPDATE for saved skills')