feat(bridge): protocol 13 with RunicNPC, edge → main (runicnpc 9e step 3, merge 2 of 3) #29

Merged
whitlocktech merged 32 commits from edge into main 2026-10-09 02:20:28 -05:00
Showing only changes of commit e5f04e0c0c - Show all commits

View File

@@ -1875,7 +1875,22 @@ namespace Oxide.Plugins
// two meanings of one word would be two answers to "how many NPCs did I kill".
// `animalKills` counts it AGAIN, separately (§5.2): the public NPC column keeps its
// meaning mid-wipe, and the site takes the human NPCs as the difference.
if (entity is BaseNpc)
//
// Rust's own animals are now `Rust.Ai.Gen2.BaseNPC2` — stag, boar, wolf, bears, big cats,
// crocodile, farm animals, critters, sea life — and not `BaseNpc`, which is all this
// tested until the RunicNPC 9d walk found no animal kill had counted at all. `BaseNpc`
// stays for whatever still derives from it. `ScientistNPC2` is the one person among
// them, so it is a human NPC kill, not an animal.
if (entity is Rust.Ai.Gen2.ScientistNPC2)
{
Tally tally = TallyFor(attacker);
tally.NpcKills++;
tally.Killed(info, entity, false);
CreditKill(attacker, false);
return;
}
if (entity is BaseNpc || entity is Rust.Ai.Gen2.BaseNPC2)
{
Tally tally = TallyFor(attacker);
tally.NpcKills++;
@@ -2065,55 +2080,56 @@ namespace Oxide.Plugins
});
}
// A syringe on a downed player raises `OnPlayerRevive` and then `OnHealingItemUse` for the
// same use; one act of help is one heal. The revive is remembered for the frame it happened in.
private ulong _reviveHealer;
private ulong _reviveTarget;
private int _reviveFrame = -1;
// A syringe on a downed player raises `OnHealingItemUse` and then, from inside the same
// `GiveEffectsTo`, `OnPlayerRevive`; one act of help is one heal. The last one counted is
// remembered for the frame it happened in, and the other hook skips the same pair.
private ulong _helpHealer;
private ulong _helpTarget;
private int _helpFrame = -1;
/// <summary>
/// Void: a non-null return refuses the heal. <paramref name="target"/> is what is healed;
/// the tool's owner is who heals. Healing yourself is not a heal (D174).
///
/// <para>
/// The target is taken as <c>object</c>: the game's `GiveEffectsTo` now takes an
/// `IMedicalToolTarget`, which is not always a player, and a parameter typed
/// `BasePlayer` would simply never be called for the hook's current shape. Only a
/// player healed counts.
/// </para>
/// </summary>
private void OnHealingItemUse(MedicalTool tool, object target)
/// <summary>Counts one act of help unless it is yourself, an NPC, or the other hook already did this frame.</summary>
private void CountHelp(BasePlayer healer, BasePlayer player)
{
MarkHook("OnHealingItemUse");
BasePlayer player = target as BasePlayer;
BasePlayer healer = tool != null ? tool.GetOwnerPlayer() : null;
if (healer == null || healer.IsNpc || player == null || player.IsNpc
|| (ulong)healer.userID == (ulong)player.userID)
return;
if (_reviveFrame == UnityEngine.Time.frameCount
&& _reviveHealer == (ulong)healer.userID && _reviveTarget == (ulong)player.userID)
int frame = UnityEngine.Time.frameCount;
if (_helpFrame == frame && _helpHealer == (ulong)healer.userID && _helpTarget == (ulong)player.userID)
return;
_helpHealer = healer.userID;
_helpTarget = player.userID;
_helpFrame = frame;
TallyFor(healer).Healed++;
}
/// <summary>
/// Void: a non-null return refuses the heal. Healing yourself is not a heal (D174).
///
/// <para>
/// Rust's `MedicalTool.GiveEffectsTo(fromPlayer, toTarget)` raises it as
/// <c>(tool, fromPlayer, toTarget)</c>. Until the RunicNPC 9d walk this took two
/// parameters, so the second — the healer — arrived as the target, every heal looked like
/// healing yourself, and none counted. The target is <c>object</c>: `IMedicalToolTarget`
/// is not always a player, and only a player healed counts.
/// </para>
/// </summary>
private void OnHealingItemUse(MedicalTool tool, BasePlayer fromPlayer, object target)
{
MarkHook("OnHealingItemUse");
CountHelp(fromPlayer ?? (tool != null ? tool.GetOwnerPlayer() : null), target as BasePlayer);
}
/// <summary>Void: a non-null return refuses the revive. Reviving yourself is not possible, and is not counted.</summary>
private void OnPlayerRevive(BasePlayer reviver, BasePlayer player)
{
MarkHook("OnPlayerRevive");
if (reviver == null || reviver.IsNpc || player == null || player.IsNpc
|| (ulong)reviver.userID == (ulong)player.userID)
return;
_reviveHealer = reviver.userID;
_reviveTarget = player.userID;
_reviveFrame = UnityEngine.Time.frameCount;
TallyFor(reviver).Healed++;
CountHelp(reviver, player);
}
/// <summary>No return behaviour. One rocket leaving a launcher.</summary>