Implement native bot recruitment and player admission, leader-owned destinations, intent-specific capacities, preparation scheduling and shared graph and flight travel. Support native group instance visits and separate raid entrances. Include pending personality-driven faction PvP and solo fleeing, preserving the absolute group fleeing exclusion. Add regression fixtures, migration, documentation and test-server evidence.
68 lines
4.4 KiB
Python
68 lines
4.4 KiB
Python
"""Run the production PvP selector against faction, legality and navigation fixtures."""
|
|
from pathlib import Path
|
|
import subprocess, tempfile
|
|
root=Path(__file__).resolve().parents[2]
|
|
s=(root/'src/server/game/World/AdventureCombatMgr.cpp').read_text()
|
|
a=s.index('Unit* AdventureCombatMgr::PvPTarget');b=s.index('Creature* AdventureCombatMgr::Proactive',a)
|
|
code=r'''
|
|
#include "AdventureCombatPolicy.h"
|
|
#include <cassert>
|
|
#include <vector>
|
|
#include <unordered_map>
|
|
#include <string>
|
|
constexpr int ALLIANCE=0,POWER_MANA=0,FACTION_GROUP_MASK_HORDE=4,FACTION_GROUP_MASK_ALLIANCE=2;
|
|
struct Player;struct Creature;
|
|
struct Faction{unsigned FactionGroup=4;};
|
|
struct Guid{int GetCounter(){return 29;}};
|
|
struct Unit{unsigned level=60;float distance=10;bool valid=true,hostile=true,reachable=true;Faction faction;
|
|
virtual Player* ToPlayer(){return nullptr;}virtual Creature* ToCreature(){return nullptr;}
|
|
unsigned getLevel(){return level;}Faction*GetFactionTemplateEntry(){return &faction;}};
|
|
struct Creature:Unit{bool controlled=false,elite=false,boss=false;Creature*ToCreature()override{return this;}
|
|
bool GetControllingPlayer(){return controlled;}bool isElite(){return elite;}bool isWorldBoss(){return boss;}};
|
|
std::vector<Player*> players;std::vector<Creature*> creatures;
|
|
struct Player:Unit{int team=1,powerType=1;float health=100;unsigned mana=100;
|
|
Player*ToPlayer()override{return this;}int GetTeam(){return team;}Guid GetGUID(){return {};}
|
|
float GetHealthPct(){return health;}int GetPowerType(){return powerType;}unsigned GetMaxPower(int){return 100;}unsigned GetPower(int){return mana;}
|
|
bool IsHostileTo(Unit*t){return t->hostile;}float GetExactDist(Unit*t){return t->distance;}
|
|
void GetPlayerListInGrid(std::vector<Player*>&v,float){v=players;}void GetCreatureListWithEntryInGrid(std::vector<Creature*>&v,int,float){v=creatures;}};
|
|
struct Profile{std::unordered_map<std::string,float>Personality{{"adventurousness",1},{"danger_tolerance",1}};}profile;
|
|
struct Lua{Profile*GetAdventureProfile(int){return &profile;}}lua;
|
|
struct Behavior{std::string intent="adventure";std::string CombatIntent(Player*){return intent;}}behavior;
|
|
auto sClientlessLuaEngine=&lua;auto sAdventureBehaviorMgr=&behavior;
|
|
float roll=0;float frand(float,float){return roll;}
|
|
struct AdventureCombatMgr{bool Valid(Player*,Unit*t,bool)const{return t->valid;}bool Reachable(Player*,Unit*t)const{return t->reachable;}
|
|
Unit*PvPTarget(Player*)const;};
|
|
'''+s[a:b]+r'''
|
|
int main(){
|
|
using namespace AdventureCombatPolicy;
|
|
assert(PvPLevel(60,55)&&PvPLevel(60,65)&&!PvPLevel(60,54)&&!PvPLevel(60,66));
|
|
assert(PvPLevel(1,6)&&!PvPLevel(1,7));
|
|
assert(PvPWillingness("rest",1,1)==0&&PvPWillingness("",1,1)==0);
|
|
assert(PvPWillingness("adventure",0,1)==0);
|
|
assert(PvPWillingness("adventure",1,1)>PvPWillingness("economy",1,1));
|
|
Player bot,enemy;bot.team=ALLIANCE;players={&enemy};AdventureCombatMgr mgr;
|
|
assert(mgr.PvPTarget(&bot)==&enemy);
|
|
for(unsigned level:{54u,66u}){enemy.level=level;assert(!mgr.PvPTarget(&bot));}enemy.level=55;
|
|
assert(mgr.PvPTarget(&bot)==&enemy);enemy.level=65;assert(mgr.PvPTarget(&bot)==&enemy);
|
|
enemy.distance=50;assert(mgr.PvPTarget(&bot)==&enemy);enemy.distance=50.1;assert(!mgr.PvPTarget(&bot));enemy.distance=10;
|
|
enemy.team=ALLIANCE;assert(!mgr.PvPTarget(&bot));enemy.team=1;
|
|
enemy.valid=false;assert(!mgr.PvPTarget(&bot));enemy.valid=true;
|
|
enemy.reachable=false;assert(!mgr.PvPTarget(&bot));enemy.reachable=true;
|
|
enemy.hostile=false;assert(!mgr.PvPTarget(&bot));enemy.hostile=true;
|
|
behavior.intent="rest";assert(!mgr.PvPTarget(&bot));behavior.intent="adventure";
|
|
bot.health=59;assert(!mgr.PvPTarget(&bot));bot.health=100;
|
|
bot.powerType=POWER_MANA;bot.mana=29;assert(!mgr.PvPTarget(&bot));bot.mana=100;
|
|
roll=1;assert(!mgr.PvPTarget(&bot));roll=0;
|
|
Creature npc;npc.distance=5;creatures={&npc};assert(mgr.PvPTarget(&bot)==&npc);
|
|
npc.faction.FactionGroup=8;assert(mgr.PvPTarget(&bot)==&enemy);npc.faction.FactionGroup=4;
|
|
npc.elite=true;assert(mgr.PvPTarget(&bot)==&enemy);npc.elite=false;
|
|
npc.controlled=true;assert(mgr.PvPTarget(&bot)==&enemy);npc.controlled=false;
|
|
npc.level=54;assert(mgr.PvPTarget(&bot)==&enemy);
|
|
}
|
|
'''
|
|
with tempfile.TemporaryDirectory() as d:
|
|
src=Path(d)/'pvp.cpp';src.write_text(code);binary=Path(d)/'pvp'
|
|
subprocess.run(['g++','-std=c++17','-I'+str(root/'src/server/game/World'),str(src),'-o',str(binary)],check=True)
|
|
subprocess.run([str(binary)],check=True)
|
|
print('Production PvP selector: level boundaries, radius, factions, native legality, navigation, intent, personality and resources passed.')
|