mirror of
https://github.com/polserver/polserver
synced 2026-08-13 08:23:08 -04:00
* removed pol_distance/inrange* functions replaced lastxyz with Pos4d * replaced WorldIterator::InVisualRange with InMaxVisualRange returning all objects in maximum update range. Adapted each caller, they now have to check in_visual_range Multis should now be send to clients with its footprint in mind. added testscript for boat moving in/out of range * removed non pos InRange/InBox functions gamestate.update_range doesnt need to be a Vector, renamed * corrected send_action_to_inrange * replaced clip methods with general numeric type clamp function * added Range2d constructor with radius * splitted update_range. chr has now a los_size (how far can it see) and an object has a visible_size (0 for objects 1/2 footprint for multis) * use in_range instead of pol_distance * corrected order of checks * fixed warnings * fixed visual size of multis testclient added wornitems pkt support added tests for los * corechanges
263 lines
8.5 KiB
Text
263 lines
8.5 KiB
Text
use uo;
|
|
use os;
|
|
use vitals;
|
|
include "testutil";
|
|
|
|
program npc_ai()
|
|
return 1;
|
|
endprogram
|
|
|
|
exported function npc_ai_movement()
|
|
var npc:=CreateNPCFromTemplate(":testnpc:test_movement",100,100,0);
|
|
if (!npc)
|
|
return ret_error("Could not create NPC: "+npc);
|
|
endif
|
|
|
|
while(1)
|
|
sleepms(10);
|
|
if (!npc.process)
|
|
if (!npc)
|
|
break;
|
|
endif
|
|
return ret_error(npc.getprop("testerror"));
|
|
endif
|
|
endwhile
|
|
|
|
return 1;
|
|
endfunction
|
|
|
|
function wait_for_prop(npc, propname, max_try := 50)
|
|
while(npc and max_try > 0)
|
|
sleepms(10);
|
|
max_try--;
|
|
var prop := npc.getprop(propname);
|
|
if (prop.errortext == "Property not found")
|
|
continue;
|
|
endif
|
|
return prop;
|
|
endwhile
|
|
return ret_error("Timeout waiting for {} on serial {}".format(propname, npc.serial));
|
|
endfunction
|
|
|
|
exported function npc_enteredarea()
|
|
return npc_test_areaevents(":testnpc:test_enteredarea", 1);
|
|
endfunction
|
|
|
|
exported function npc_enteredarea_npconly()
|
|
return npc_test_areaevents(":testnpc:test_enteredarea_onlynpc", 1);
|
|
endfunction
|
|
|
|
exported function npc_enteredarea_pconly()
|
|
return npc_test_areaevents(":testnpc:test_enteredarea_onlypc", 0);
|
|
endfunction
|
|
|
|
function npc_test_areaevents(template, expected_to_see)
|
|
var x := 100;
|
|
var y := 100;
|
|
var range := 10; // defined in ai_enteredarea.src
|
|
|
|
var npc := CreateNPCFromTemplate(template,x,y,0);
|
|
if (!npc)
|
|
return ret_error("Could not create NPC: "+npc);
|
|
endif
|
|
|
|
var ready := wait_for_prop(npc, "ready");
|
|
if (ready.errortext)
|
|
return ready;
|
|
endif
|
|
|
|
// test if it can see npcs created at the four borders of the event range
|
|
var probe_npc1 := CreateNPCFromTemplate(":testnpc:probe_npc",x+range,y+range,0);
|
|
var probe_npc2 := CreateNPCFromTemplate(":testnpc:probe_npc",x-range,y-range,0);
|
|
var probe_npc3 := CreateNPCFromTemplate(":testnpc:probe_npc",x-range,y+range,0);
|
|
var probe_npc4 := CreateNPCFromTemplate(":testnpc:probe_npc",x+range,y-range,0);
|
|
|
|
// test if it CANT see npcs created right outside the border of the event range
|
|
var probe_npc1_notseen := CreateNPCFromTemplate(":testnpc:probe_npc",x+range,y+range+1,0);
|
|
var probe_npc2_notseen := CreateNPCFromTemplate(":testnpc:probe_npc",x-range,y-range-1,0);
|
|
var probe_npc3_notseen := CreateNPCFromTemplate(":testnpc:probe_npc",x-range-1,y+range,0);
|
|
var probe_npc4_notseen := CreateNPCFromTemplate(":testnpc:probe_npc",x+range+1,y-range,0);
|
|
|
|
// test if it can see an npc created outside, then moved in
|
|
var probe_npc_outside_then_in := CreateNPCFromTemplate(":testnpc:probe_npc",x+range+10,y-range-10,0);
|
|
MoveObjectToLocation(probe_npc_outside_then_in, x+range-2, y+range-2, 0);
|
|
|
|
// the order matters
|
|
var in_range_npcs := {
|
|
probe_npc1.serial,
|
|
probe_npc2.serial,
|
|
probe_npc3.serial,
|
|
probe_npc4.serial,
|
|
probe_npc_outside_then_in.serial
|
|
};
|
|
var nExpected := in_range_npcs.size();
|
|
|
|
if (!expected_to_see)
|
|
var who_entered := wait_for_prop(npc, "who_entered", max_try := 3);
|
|
if (who_entered.errortext)
|
|
if (who_entered.errortext["Timeout waiting for"])
|
|
//expected - go on
|
|
else
|
|
return who_entered;
|
|
endif
|
|
elseif (who_entered)
|
|
return ret_error("NPC saw other NPCs entering but shouldnt");
|
|
else
|
|
return ret_error("NPC did something odd: " + CStr(who_entered));
|
|
endif
|
|
else
|
|
var who_entered := wait_for_prop(npc, "who_entered");
|
|
if (who_entered.errortext)
|
|
return who_entered;
|
|
endif
|
|
|
|
if (who_entered.size() < nExpected)
|
|
return ret_error("NPC only received {} ENTEREDAREA events out of {}.".format(who_entered.size(), nExpected));
|
|
endif
|
|
|
|
foreach serial in who_entered
|
|
var idx := serial in in_range_npcs;
|
|
if (!idx)
|
|
return ret_error("Unexpected NPC was seen entering: {}".format(serial));
|
|
endif
|
|
if (_serial_iter != idx)
|
|
return ret_error("NPC seen entering out of order: {} / {}".format(idx, _serial_iter));
|
|
endif
|
|
endforeach
|
|
endif
|
|
|
|
// test if it can see them leaving
|
|
MoveObjectToLocation(probe_npc1, x+range+1, y+range+1, 0);
|
|
MoveObjectToLocation(probe_npc2, x-range-1, y-range-1, 0);
|
|
MoveObjectToLocation(probe_npc3, x-range-1, y+range+1, 0);
|
|
MoveObjectToLocation(probe_npc4, x+range+1, y-range-1, 0);
|
|
// this one too
|
|
MoveObjectToLocation(probe_npc_outside_then_in, x+range+20, y+range+20, 0);
|
|
|
|
// test that it DOESNT see them leaving
|
|
MoveObjectToLocation(probe_npc1_notseen, x+range+10, y+range+10, 0);
|
|
MoveObjectToLocation(probe_npc2_notseen, x-range-10, y-range-10, 0);
|
|
MoveObjectToLocation(probe_npc3_notseen, x-range-10, y+range+10, 0);
|
|
MoveObjectToLocation(probe_npc4_notseen, x+range+10, y-range-10, 0);
|
|
|
|
|
|
if (!expected_to_see)
|
|
var who_left := wait_for_prop(npc, "who_left", max_try := 3);
|
|
if (who_left.errortext)
|
|
if (who_left.errortext["Timeout waiting for"])
|
|
//expected - go on
|
|
else
|
|
return who_left;
|
|
endif
|
|
elseif (who_left)
|
|
return ret_error("NPC saw other NPCs leaving but shouldnt");
|
|
else
|
|
return ret_error("NPC did something odd: " + CStr(who_left));
|
|
endif
|
|
else
|
|
var who_left := wait_for_prop(npc, "who_left");
|
|
if (who_left.errortext)
|
|
return who_left;
|
|
endif
|
|
|
|
if (who_left.size() < nExpected)
|
|
return ret_error("NPC only received {} LEFTAREA events out of {}.".format(who_left.size(), nExpected));
|
|
endif
|
|
|
|
foreach serial in who_left
|
|
var idx := serial in in_range_npcs;
|
|
if (!idx)
|
|
return ret_error("Unexpected NPC was seen leaving: {}".format(serial));
|
|
endif
|
|
if (_serial_iter != idx)
|
|
return ret_error("NPC seen leaving out of order: {} / {}".format(idx, _serial_iter));
|
|
endif
|
|
endforeach
|
|
endif
|
|
|
|
npc.kill();
|
|
|
|
probe_npc1.kill();
|
|
probe_npc2.kill();
|
|
probe_npc3.kill();
|
|
probe_npc4.kill();
|
|
|
|
probe_npc1_notseen.kill();
|
|
probe_npc2_notseen.kill();
|
|
probe_npc3_notseen.kill();
|
|
probe_npc4_notseen.kill();
|
|
|
|
probe_npc_outside_then_in.kill();
|
|
|
|
return 1;
|
|
endfunction
|
|
|
|
exported function test_load_desc_props()
|
|
var npc:=CreateNPCFromTemplate(":testnpc:load_npc",100,100,0);
|
|
if (!npc)
|
|
return ret_error("Could not create NPC: "+npc);
|
|
endif
|
|
|
|
if (!npc.weapon.getprop("weaponcprop"))
|
|
npc.kill();
|
|
return ret_error("Failed to load weapon cprop");
|
|
endif
|
|
if (!npc.shield.getprop("shieldcprop"))
|
|
npc.kill();
|
|
return ret_error("Failed to load shield cprop");
|
|
endif
|
|
if (!npc.no_drop_exception)
|
|
npc.kill();
|
|
return ret_error("Failed to load nodropexception");
|
|
endif
|
|
|
|
npc.kill();
|
|
return 1;
|
|
endfunction
|
|
|
|
exported function test_npc_realm_move()
|
|
// crashed by wrongly converting coordinates between realms
|
|
var npc:=CreateNPCFromTemplate(":testnpc:load_npc",100,100,0);
|
|
if (!npc)
|
|
return ret_error("Could not create NPC: "+npc);
|
|
endif
|
|
|
|
MoveObjectToLocation(npc,1000,1000,0,"britannia2",MOVEOBJECT_FORCELOCATION);
|
|
if (npc.x != 1000 || npc.y != 1000 || npc.realm != "britannia2")
|
|
var res:=$"Failed initial move: {npc.x},{npc.y},{npc.realm}";
|
|
npc.kill();
|
|
return ret_error(res);
|
|
endif
|
|
|
|
MoveObjectToLocation(npc,10,10,0,"britannia",MOVEOBJECT_FORCELOCATION);
|
|
if (npc.x != 10 || npc.y != 10 || npc.realm != "britannia")
|
|
var res:=$"Failed to move: {npc.x},{npc.y},{npc.realm}";
|
|
npc.kill();
|
|
return ret_error(res);
|
|
endif
|
|
|
|
npc.kill();
|
|
return 1;
|
|
endfunction
|
|
|
|
/*
|
|
Test that with WarmodeInhibitsRegen=3 (NPCs Only), an _NPC_ in war mode _will not_ regenerate health.
|
|
*/
|
|
exported function npc_warmodeinhibitsregen()
|
|
var npc:=CreateNPCFromTemplate(":testnpc:load_npc",100,100,0);
|
|
if (!npc)
|
|
return ret_error("Could not create NPC: "+npc);
|
|
endif
|
|
|
|
npc.setwarmode(1);
|
|
SetVital( npc, "Life", GetVital( npc, "Life" ) / 2);
|
|
var damaged_health := GetVital( npc, "Life" );
|
|
Sleep(6);
|
|
var waited_health := GetVital( npc, "Life" );
|
|
npc.kill();
|
|
|
|
if (damaged_health != waited_health)
|
|
return ret_error($"NPC health changed between sleeping: {damaged_health} -> {waited_health}");
|
|
endif
|
|
return 1;
|
|
endfunction
|