48 lines
4.4 KiB
Python
48 lines
4.4 KiB
Python
"""Execute generic harmful-ground detection and safe-path choice from production."""
|
|
from pathlib import Path
|
|
import subprocess,tempfile
|
|
root=Path(__file__).resolve().parents[2]
|
|
s=(root/'src/server/game/World/AdventureEncounterMgr.cpp').read_text();a=s.index('bool AdventureEncounterMgr::AvoidGroundDamage(');b=s.index('{',a);e=b+1;depth=1
|
|
while depth:depth+=(s[e]=='{')-(s[e]=='}');e+=1
|
|
code=r'''
|
|
#include <vector>
|
|
#include <algorithm>
|
|
#include <cmath>
|
|
#include <cassert>
|
|
using uint32=unsigned;
|
|
constexpr unsigned GRID_MAP_TYPE_MASK_DYNAMICOBJECT=1,SPELL_EFFECT_SCHOOL_DAMAGE=1,SPELL_AURA_PERIODIC_DAMAGE=2,SPELL_AURA_PERIODIC_DAMAGE_PERCENT=3;
|
|
constexpr float INVALID_HEIGHT=-100000;
|
|
struct Position{float m_positionX=0,m_positionY=0,m_positionZ=0,o=0;Position()=default;Position(float x,float y,float z,float d):m_positionX(x),m_positionY(y),m_positionZ(z),o(d){}float GetPositionX()const{return m_positionX;}float GetPositionY()const{return m_positionY;}float GetPositionZ()const{return m_positionZ;}float GetOrientation()const{return o;}float GetExactDist2d(Position const*p)const{return std::hypot(m_positionX-p->m_positionX,m_positionY-p->m_positionY);}};
|
|
struct Dynamic;struct Unit{};
|
|
struct WorldObject:Position{virtual Dynamic*ToDynObject(){return nullptr;}};
|
|
struct Effect{unsigned Effect=0,ApplyAuraName=0;};struct Spell{std::vector<Effect>Effects;};
|
|
struct Dynamic:WorldObject{bool hostile=true,phase=true;float radius=6;Unit caster;Spell spell{{{0,SPELL_AURA_PERIODIC_DAMAGE}}};Dynamic*ToDynObject()override{return this;}Unit*GetCaster(){return &caster;}Spell*GetSpellInfo(){return &spell;}float GetRadius(){return radius;}};
|
|
struct Guid{unsigned GetCounter(){return 1;}};
|
|
struct Map{bool invalid=false;float GetHeight(unsigned,float,float,float,bool,float){return invalid?INVALID_HEIGHT:0;}}map;
|
|
std::vector<WorldObject*> areaObjects;
|
|
struct Player:Position{unsigned stops=0;Guid GetGUID(){return {};}Map*GetMap(){return ↦}unsigned GetPhaseShift(){return 169;}bool IsInPhase(Dynamic*d){return d->phase;}bool IsHostileTo(Unit*u){for(auto obj:areaObjects)if(auto d=obj->ToDynObject())if(&d->caster==u)return d->hostile;return false;}void CastStop(){++stops;}};
|
|
namespace Trinity{template<class Check>struct WorldObjectListSearcher{std::vector<WorldObject*>&objects;Check✓WorldObjectListSearcher(Player*,std::vector<WorldObject*>&v,Check&c,unsigned):objects(v),check(c){}};}
|
|
namespace Cell{template<class T>void VisitAllObjects(Player*,T&search,float){for(auto obj:areaObjects)if(search.check(obj))search.objects.push_back(obj);}}
|
|
enum class ClientlessTravelState{Moving,Arrived};struct Status{ClientlessTravelState State=ClientlessTravelState::Moving;Position Target;};
|
|
struct ClientlessPathDiagnostics{bool Complete=true,Suspicious=false;float PathLength=0;};
|
|
struct Travel{bool present=false,path=true;unsigned starts=0;Status status;Status*GetStatus(unsigned){return present?&status:nullptr;}bool AnalyzePath(Player*p,Position const&point,ClientlessPathDiagnostics&d){d.PathLength=p->GetExactDist2d(&point);return path;}bool StartTravel(Player*,Position const&point){++starts;present=true;status.Target=point;return true;}}travel;auto sClientlessTravelMgr=&travel;
|
|
struct AdventureEncounterMgr{bool AvoidGroundDamage(Player*);};
|
|
'''+s[a:e]+r'''
|
|
int main(){
|
|
AdventureEncounterMgr mgr;Player p;Dynamic hostile,friendly;areaObjects={&hostile,&friendly};friendly.hostile=false;friendly.m_positionX=10;
|
|
assert(mgr.AvoidGroundDamage(&p));assert(travel.starts==1 && p.stops==1 && travel.status.Target.GetExactDist2d(&hostile)>=8);
|
|
assert(mgr.AvoidGroundDamage(&p));assert(travel.starts==1 && p.stops==1); // existing safe destination retained
|
|
p.m_positionX=20;assert(!mgr.AvoidGroundDamage(&p));
|
|
p.m_positionX=0;travel.present=false;travel.path=false;assert(!mgr.AvoidGroundDamage(&p));assert(travel.starts==1);
|
|
travel.path=true;map.invalid=true;assert(!mgr.AvoidGroundDamage(&p));map.invalid=false;
|
|
hostile.phase=false;assert(!mgr.AvoidGroundDamage(&p));hostile.phase=true;
|
|
hostile.m_positionZ=8;assert(!mgr.AvoidGroundDamage(&p));hostile.m_positionZ=0;
|
|
hostile.spell.Effects.clear();assert(!mgr.AvoidGroundDamage(&p));
|
|
}
|
|
'''
|
|
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 ground avoidance: harmful/friendly, phase169, height, reachable safe endpoint, rejected paths and reuse without cast/movement thrashing passed')
|