diff --git a/tools/RunicNpcTest.cs b/tools/RunicNpcTest.cs
index c5175ce..d4dd848 100644
--- a/tools/RunicNpcTest.cs
+++ b/tools/RunicNpcTest.cs
@@ -422,6 +422,31 @@ namespace Oxide.Plugins
arg.ReplyWith("rnt: rocket probe started");
}
+ /// A probe: an escort follows a scientist 35 m, the scientist is killed, then 30 s of what the escort does.
+ [ConsoleCommand("rnt.escortprobe")]
+ private void CmdEscortProbe(ConsoleSystem.Arg arg)
+ {
+ if (arg.Connection != null && !arg.IsAdmin) return;
+ Vector3 f;
+ if (!FindField(300f, 2025, out f)) return;
+ BasePlayer keeper = StandIn(f + new Vector3(0, 0, 60), 50);
+ Vector3 c = OnMesh(f);
+ ScientistNPC charge = SpawnScientist(c + new Vector3(5, 0, 0));
+ BasePlayer escort = Spawn(c, "t_roam");
+ Api("RunicNpc_Escort", Id(escort), charge);
+ int n = 0;
+ timer.Repeat(2f, 30, () =>
+ {
+ n++;
+ if (n == 3) Teleport(charge, c + new Vector3(0, 0, 35));
+ if (n == 12 && !Gone(charge)) charge.Kill();
+ Dictionary d = Gone(escort) ? null : Describe(escort);
+ Puts($"[esc {n}] state={d?["state"]} rest={d?["rest"]} escort={d?["escort"] ?? "null"} target={TargetOf(d)} engaged={d?["engaged"]} home={(d == null ? -1f : Flat(escort.transform.position, V(d["home"]))):0.0} ended={_escortEnded.Count}");
+ if (n == 30) { Api("RunicNpc_DespawnOwner", Owner); ClearWorld(); }
+ });
+ arg.ReplyWith("rnt: escort probe started");
+ }
+
[ConsoleCommand("rnt.clear")]
private void CmdClear(ConsoleSystem.Arg arg)
{
@@ -1582,7 +1607,9 @@ namespace Oxide.Plugins
Check("s5.escort.set", said == null, said ?? "escorting");
yield return new WaitForSeconds(2f);
Vector3 home = escort.transform.position;
- Teleport(charge, c + new Vector3(0, 0, 35));
+ // East, not north: north brings the escort within sense range of the keeper stand-in, and Rust's
+ // design then fights it instead of walking home.
+ Teleport(charge, c + new Vector3(35, 0, 0));
float closest = float.MaxValue;
for (int t = 0; t < 20; t++)
{