// ReSharper disable once UseNegatedPatternMatching, LoopCanBeConvertedToQuery public void OnItemTakenFromPlayer(CharacterInventory inventory, Client yoinker, Item item) { Client targetClient = GameMain.Server.ConnectedClients.Find(c => c.Character == inventory.Owner); Character yoinkerCharacter = yoinker?.Character; Character targetCharacter = inventory.Owner as Character; if (yoinker == null || item == null || yoinkerCharacter == null || targetCharacter == null || yoinkerCharacter == targetCharacter) { return; } if (targetClient == null && (!DangerousItemStealBots || targetCharacter.AIController == null)) { return; } // Only if the target is alive and they are stunned, unconscious or handcuffed if (targetCharacter.IsDead || targetCharacter.Removed || !(targetCharacter.Stun > 0) && !targetCharacter.IsUnconscious && !targetCharacter.LockHands) { return; } if (GameMain.Server.TraitorManager?.Traitors != null) { if (GameMain.Server.TraitorManager.Traitors.Any(t => t.Character == targetCharacter || t.Character == yoinkerCharacter)) { // Don't penalize traitors return; } } var foundItem = Inventory.FindItemRecursive(item, it => it.Prefab.Identifier == "idcard" || it.GetComponent <RangedWeapon>() != null || it.GetComponent <MeleeWeapon>() != null); if (foundItem == null) { return; } bool isIdCard = foundItem.prefab.Identifier == "idcard"; bool isWeapon = foundItem.GetComponent <RangedWeapon>() != null || foundItem.GetComponent <MeleeWeapon>() != null; if (isIdCard) { string name = string.Empty; foreach (var tag in foundItem.Tags.Split(',')) { string[] split = tag.Split(':'); string key = split.Length > 0 ? split[0] : string.Empty; string value = split.Length > 1 ? split[1] : string.Empty; if (key == "name") { name = value; } } // Name tag doesn't belong to anyone in particular or we own the ID card if (name == null || name == yoinkerCharacter.Name) { return; } } if (MathUtils.NearlyEqual(DangerousItemStealKarmaDecrease, 0)) { return; } const float calcUpper = 1, calcLower = -1; float upper = DangerousItemStealKarmaDecrease + 10.0f; float lower = DangerousItemStealKarmaDecrease - 10.0f; if (lower < 0) { upper += Math.Abs(lower); lower = 0; } // If we're stealing from a bot assume the bot has 50 karma var targetKarma = targetClient?.Karma ?? 50; float karmaDifference = Math.Clamp((targetKarma - yoinker.Karma) / 50.0f, calcLower, calcUpper); float karmaDecrease = lower + (karmaDifference - calcLower) * (upper - lower) / (calcUpper - calcLower); JobPrefab clientJob = yoinker.CharacterInfo?.Job?.Prefab; // security officers receive less karma penalty if (clientJob != null && clientJob.Identifier == "securityofficer" && isWeapon) { karmaDecrease *= 0.5f; } AdjustKarma(yoinkerCharacter, -karmaDecrease, "Stolen dangerous item"); }