Support persistent residents with normal resurrection and closer companions
Core tests / core (push) Successful in 2m54s
Core tests / core (push) Successful in 2m54s
This commit is contained in:
@@ -48,3 +48,9 @@ test('companion ranking prefers complementary native roles and shared active que
|
||||
const {companionScore}=require('../.test-build/community.js');const a=bot('A'),b=bot('B'),c=bot('C');a.world.combatRole='tank';b.world.combatRole='healer';c.world.combatRole='damage';assert.ok(companionScore(a,b)>companionScore(a,c));
|
||||
b.world.combatRole='damage';a.world.quests=[1,2];c.world.quests=[1,2];assert.ok(companionScore(a,c)>companionScore(a,b));
|
||||
});
|
||||
|
||||
test('adventuring companions stay within five levels',()=>{
|
||||
const a=bot('A'),b=bot('B');b.level=a.level+6;
|
||||
assert.equal(partyDecision(a,b).accepted,false);
|
||||
b.level=a.level+5;assert.equal(partyDecision(a,b).accepted,true);
|
||||
});
|
||||
|
||||
@@ -92,3 +92,15 @@ test('unverified bridge death fails safe without erasing identity',async()=>{
|
||||
await applyAuthoritativeAleEvent(store,'player.snapshot',{roster:true,observedAt:100,characterGuids:[123]});
|
||||
assert.equal(store.state.bots.filter(b=>b.status==='online').length,0);
|
||||
});
|
||||
|
||||
test('normal resurrection mode preserves memories and identity across death and later snapshot',async()=>{
|
||||
const store=new Store();store.state.settings.hardcore.enabled=false;
|
||||
const bot=store.state.bots.find(b=>b.id==='bot-6');
|
||||
bot.memories.push({id:'keep',text:'My companion',importance:8,source:'observation',at:new Date().toISOString()});
|
||||
const payload={name:bot.name,isBot:true,characterGuid:99,accountId:2,healthPct:0};
|
||||
await applyAuthoritativeAleEvent(store,'player.killed-by-creature',payload);
|
||||
assert.notEqual(store.state.bots.find(b=>b.id===bot.id).status,'dead');
|
||||
await applyAuthoritativeAleEvent(store,'player.snapshot',{...payload,healthPct:100});
|
||||
const revived=store.state.bots.find(b=>b.id===bot.id);
|
||||
assert.equal(revived.death,undefined);assert.ok(revived.memories.some(m=>m.id==='keep'));
|
||||
});
|
||||
|
||||
@@ -20,10 +20,12 @@ function player(guid,name,account,level,dead)
|
||||
players[name]=p; return p
|
||||
end
|
||||
function AuthDBQuery(sql)
|
||||
if string.find(sql,"azerothai_realm_rules",1,true) then return {GetUInt32=function()return mode or 1 end} end
|
||||
if string.find(sql,'SELECT id FROM account',1,true) then
|
||||
if string.find(sql,'id=99 ',1,true) then return nil end
|
||||
return {GetUInt32=function() return 2 end}
|
||||
end
|
||||
if string.find(sql,"SELECT guid,name,account_id FROM azerothai_lifecycle WHERE state='dead'",1,true) then return nil end
|
||||
local q={i=1}
|
||||
function q:GetUInt32(n) return rows[self.i][n+1] end
|
||||
function q:GetString(n) return rows[self.i][n+1] end
|
||||
@@ -131,3 +133,9 @@ assert(entries==2,'Death Knights must be audited at level 55')
|
||||
events[8](8,nil,players.HordeDK);tick();assert(not players.HordeDK and deaths==1)
|
||||
""")
|
||||
print('PASS: retirement, protection, level-1 entry, replay safety, and 25/25 faction balancing')
|
||||
|
||||
normal=LuaRuntime();normal.execute(setup)
|
||||
normal.execute("mode=0;players={};rows={};for i=1,25 do rows[#rows+1]={100+i,'Resident'..i,2,0,'active',2};player(100+i,'Resident'..i,2,5,i==1) end;rows[#rows+1]={200,'Reserve',2,0,'reserve',2};player(200,'Reserve',2,1,false)")
|
||||
normal.execute((Path(__file__).parents[1]/'ale/azerothai_lifecycle.lua').read_text())
|
||||
normal.execute("events[8](8,nil,players.Resident1);tick();assert(players.Resident1 and deaths==0);assert(not players.Reserve,'Recoverable death must retain its population slot');local n=0;for _ in pairs(players)do n=n+1 end;assert(n==25)")
|
||||
print('Normal resurrection mode preserves identity and reserves the dead resident population slot')
|
||||
|
||||
@@ -44,9 +44,9 @@ l=new();l.execute("group();AzerothAISetSurvivalEnabled(false);step(0);assert(#ca
|
||||
print('Native survival: retreat cooldown, recovery, regroup range, human-party protection, and disabled grouping passed')
|
||||
|
||||
l=new();l.execute("A.combat=true;A.hp=45;A.cast=true;step(0);assert(A.interrupted and calls[1]=='flee')")
|
||||
l=new();l.execute("A.combat=true;A.hp=100;A.enemy={GetLevel=function()return 8 end,ToCreature=function()return nil end,IsHostileTo=function()return true end};step(0);assert(calls[1]=='flee')")
|
||||
l=new();l.execute("A.combat=true;A.hp=100;A.enemy={GetGUID=function()return 999 end,GetLevel=function()return 8 end,ToCreature=function()return nil end,IsHostileTo=function()return true end};step(0);assert(calls[1]=='flee')")
|
||||
l=new();l.execute("A.selected={GetGUID=function()return 99 end,GetLevel=function()return 5 end,ToCreature=function(self)return self end,GetRank=function()return 1 end,IsHostileTo=function()return true end};step(0);assert(A.attackStopped and calls[1]=='flee')")
|
||||
l=new();l.execute("A.friendly=true;A.selected={GetLevel=function()return 80 end,ToCreature=function()return nil end};step(0);assert(#calls==0)")
|
||||
l=new();l.execute("A.friendly=true;A.selected={GetGUID=function()return 999 end,GetLevel=function()return 80 end,ToCreature=function()return nil end};step(0);assert(#calls==0)")
|
||||
l=new();l.execute("A.combat=true;A.hp=40;step(0);A.x=10;step(2);A.combat=false;step(2);local found=false;for _,q in pairs(auditRows)do if string.find(q,'6F75742D6F662D636F6D626174') then found=true end end;assert(found)")
|
||||
l=new();l.execute("A.combat=true;A.hp=40;step(0);A.hp=70;step(30);assert(string.find(auditRows[#auditRows], '6E6F2D6D6F76656D656E74'))")
|
||||
l=new();l.execute("group();B.distance=150;step(0);assert(B.master==A)")
|
||||
@@ -59,3 +59,5 @@ l=new();l.execute("A.combat=true;A.hp=75;A.attackers={1,2};step(0);assert(calls[
|
||||
l=new();l.execute("A.combat=true;step(0);A.hp=75;step(2);assert(calls[1]=='flee')")
|
||||
l=new();l.execute("A.hp=80;step(0);A.hp=100;local query=AuthDBQuery;function AuthDBQuery(sql)if string.find(sql,'survival_holds WHERE guid=1',1,true) then return {GetUInt32=function(_,i)return ({[0]=1,[2]=11,[3]=1,[4]=0,[5]=0,[6]=0,[7]=0})[i] end,GetString=function()return 'A' end} end;return query(sql)end;step(30);assert(A.strategies.rpg==true);assert(not AzerothAISurvivalOverride(A))")
|
||||
print('Readiness holds, mana recovery, outnumbered/rapid-loss retreat, and original-strategy restoration passed')
|
||||
l=new();l.execute("A.combat=true;A.hp=75;A.attackers={1,2};A.enemy={GetGUID=function()return 999 end,GetLevel=function()return 5 end,ToCreature=function()return nil end};step(0);A.selected=A.enemy;A.combat=false;A.hp=100;A.attackers={};step(20);assert(A.attackStopped and calls[#calls]=='flee');A.attackStopped=false;step(601);assert(not A.attackStopped)")
|
||||
print('Dangerous encounter target avoidance expires after ten minutes')
|
||||
|
||||
Reference in New Issue
Block a user