Expand auto-hunt pursuit ranges and show server bonus effects

This commit is contained in:
shen
2026-09-30 23:02:04 -07:00
parent 922954dd97
commit eb5833747a
22 changed files with 676 additions and 82 deletions
+47 -3
View File
@@ -12,7 +12,7 @@
#include <cmath>
#include <cstdint>
using DWORD = uint32_t;
constexpr int ENTITY_CHARACTER=1, ATTR_BANPK=4, MOB_RANK_BOSS=4, CHAT_TYPE_COMMAND=5;
constexpr int ENTITY_CHARACTER=1, ATTR_BANPK=4, MOB_RANK_BOSS=4, CHAT_TYPE_COMMAND=5, SECTREE_SIZE=6400;
struct Character;
using LPCHARACTER=Character*;
struct Entity { virtual ~Entity() {} bool IsType(int) { return true; } };
@@ -22,6 +22,7 @@ struct Sectree {
bool safe=false;
std::vector<Entity*> entities;
DWORD GetAttribute(long,long) { return safe ? ATTR_BANPK : 0; }
template<class F> void for_each_entity(F& f) { for(auto* e:entities) f(e); }
template<class F> void ForEachAround(F& f) { for(auto* e:entities) f(e); }
};
struct Character: Entity {
@@ -44,6 +45,7 @@ struct Character: Entity {
int GetX() { return x; }
int GetY() { return y; }
int GetMapIndex() { return 1; }
DWORD GetPlayerID() { return vid; }
int GetMobRank() { return rank; }
Sectree* GetSectree() { return sec; }
Party* GetParty() { return party; }
@@ -62,6 +64,26 @@ struct CHARACTER_MANAGER {
static CHARACTER_MANAGER& instance() { static CHARACTER_MANAGER value; return value; }
Character* Find(DWORD vid) { return mobs[vid]; }
};
using LPSECTREE=Sectree*;
struct SectreeMap {
std::map<std::pair<int,int>, Sectree*> cells;
template<class F> void for_each_in_rect(int x0,int y0,int x1,int y1,F& f) {
for (const auto& cell:cells)
if (cell.first.first>=x0/SECTREE_SIZE && cell.first.first<=x1/SECTREE_SIZE &&
cell.first.second>=y0/SECTREE_SIZE && cell.first.second<=y1/SECTREE_SIZE)
cell.second->for_each_entity(f);
}
Sectree* Find(int x,int y) {
auto it=cells.find({x/SECTREE_SIZE,y/SECTREE_SIZE});
return it==cells.end() ? nullptr : it->second;
}
};
using LPSECTREE_MAP=SectreeMap*;
struct SECTREE_MANAGER {
SectreeMap map;
static SECTREE_MANAGER& instance() { static SECTREE_MANAGER m; return m; }
SectreeMap* GetMap(int) { return &map; }
};
int now=100;
int get_global_time() { return now; }
#define DISTANCE_APPROX(x,y) int(std::hypot(x,y))
@@ -71,7 +93,8 @@ int get_global_time() { return now; }
int main() {
Sectree sec;
Character owner; owner.pc=true; owner.sec=&sec;
Character owner; owner.pc=true; owner.sec=&sec; owner.vid=1;
SECTREE_MANAGER::instance().map.cells[{0,0}]=&sec;
Character other; other.pc=true;
std::vector<Party> parties(25);
std::vector<Character> mobs(50);
@@ -104,9 +127,30 @@ int main() {
assert(owner.replies.back()=="AutoHuntGather 11 done 0");
sec.safe=false; owner.replies.clear();
do_autohunt_pull(&owner,"21 5000 0 12");
do_autohunt_pull(&owner,"3 5001 0 12");
do_autohunt_pull(&owner,"3 15001 0 12");
do_autohunt_pull(&owner,"3 5000 0 12 extra");
assert(owner.replies.empty());
// Large ranges visit distant sectors and extend only the selected owner's pursuit.
Sectree distant;
Character far; far.vid=1000; far.x=14000; far.sec=&distant;
distant.entities.push_back(&far);
SECTREE_MANAGER::instance().map.cells[{2,0}]=&distant;
CHARACTER_MANAGER::instance().mobs[far.vid]=&far;
sec.entities.clear(); now+=10;
do_autohunt_pull(&owner,"20 10000 0 13");
assert(owner.replies.back()=="AutoHuntGather 13 done 0" && !far.victim);
now+=10;
do_autohunt_pull(&owner,"20 15000 0 14");
assert(owner.replies.back()=="AutoHuntGather 14 done 1" && far.victim==&owner);
assert(AutoHuntPullLeash(&far,&owner)==15001);
assert(AutoHuntPullLeash(&mobs[49],&owner)==4000);
do_autohunt_pull(&owner,"0 15000 0 15");
assert(AutoHuntPullLeash(&far,&owner)==4000);
now+=10; do_autohunt_pull(&owner,"3 15000 0 16");
assert(AutoHuntPullLeash(&far,&other)==4000);
now+=10; do_autohunt_pull(&owner,"3 15000 0 17");
now+=180;
assert(AutoHuntPullLeash(&far,&owner)==4000);
// Unequal group sizes, exact 10-group cap and nearest ordering independent of input order.
std::vector<mt_autohunt::Candidate> candidates;
for(int g=24;g>=0;--g)