41 lines
2.5 KiB
Python
41 lines
2.5 KiB
Python
"""Execute native tier-based skill preparation before world insertion."""
|
|
from pathlib import Path
|
|
import subprocess,tempfile
|
|
root=Path(__file__).resolve().parents[2]
|
|
s=(root/'src/server/game/World/ClientlessCharacterFactory.cpp').read_text()
|
|
a=s.index('bool ClientlessCharacterFactory::PrepareSkillRank(')
|
|
code=r'''
|
|
#include <cassert>
|
|
#include <unordered_map>
|
|
using uint32=unsigned;constexpr unsigned MAX_SKILL_STEP=16;
|
|
struct RC{unsigned MinLevel=5,SkillTierID=1;}rc;
|
|
struct DBC {bool available=true;RC*GetSkillRaceClassInfo(unsigned,unsigned,unsigned){return available?&rc:nullptr;}}sDBCManager;
|
|
struct Tier{unsigned Value[16]={75,150,225,300,375,450,525};}tier;
|
|
struct Store{bool available=true;Tier*LookupEntry(unsigned){return available?&tier:nullptr;}}sSkillTiersStore;
|
|
struct Player{
|
|
bool inWorld=false;unsigned level=60,step=0,value=0,cap=0;int writes=0;
|
|
bool IsInWorld(){return inWorld;}unsigned getRace(){return 1;}unsigned getClass(){return 1;}unsigned getLevel(){return level;}
|
|
unsigned GetSkillStep(unsigned){return step;}unsigned GetPureSkillValue(unsigned){return value;}unsigned GetPureMaxSkillValue(unsigned){return cap;}
|
|
void SetSkill(unsigned,unsigned s,unsigned v,unsigned c){++writes;step=s;value=v;cap=c;}
|
|
};
|
|
struct ClientlessCharacterFactory{static bool PrepareSkillRank(Player*,unsigned,unsigned);};
|
|
'''+s[a:]+r'''
|
|
int main(){
|
|
Player p;using F=ClientlessCharacterFactory;
|
|
assert(F::PrepareSkillRank(&p,186,1));assert(p.step==1 && p.value==75 && p.cap==75);
|
|
assert(F::PrepareSkillRank(&p,186,5));assert(p.step==5 && p.value==375 && p.cap==375);
|
|
auto previous=p.writes;assert(F::PrepareSkillRank(&p,186,1));assert(p.step==5 && p.writes==previous);
|
|
assert(!F::PrepareSkillRank(&p,186,0));assert(!F::PrepareSkillRank(&p,186,17));assert(!F::PrepareSkillRank(&p,186,8));
|
|
p.inWorld=true;assert(!F::PrepareSkillRank(&p,186,6));p.inWorld=false;
|
|
p.level=4;assert(!F::PrepareSkillRank(&p,186,6));p.level=60;
|
|
sDBCManager.available=false;assert(!F::PrepareSkillRank(&p,186,6));sDBCManager.available=true;
|
|
sSkillTiersStore.available=false;assert(!F::PrepareSkillRank(&p,186,6));
|
|
assert(p.writes==previous);assert(!F::PrepareSkillRank(nullptr,186,1));
|
|
}
|
|
'''
|
|
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('Production offline skill preparation: native tier caps, no downgrading, rank/level/race/tier gates and no modification of online players passed')
|