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++) {