private ClientMemory GetClientMemory(Client client) { if (!clientMemories.ContainsKey(client)) { clientMemories[client] = new ClientMemory() { PreviousNotifiedKarma = client.Karma }; } return(clientMemories[client]); }
public void OnWireDisconnected(Character character, Wire wire) { if (character == null || wire == null) { return; } Client client = GameMain.Server.ConnectedClients.Find(c => c.Character == character); if (client == null) { return; } if (!clientMemories.ContainsKey(client)) { clientMemories[client] = new ClientMemory(); } clientMemories[client].WireDisconnectTime.RemoveAll(w => w.First == wire); clientMemories[client].WireDisconnectTime.Add(new Pair <Wire, float>(wire, (float)Timing.TotalTime)); }
public void OnCharacterHealthChanged(Character target, Character attacker, float damage, float stun, IEnumerable <Affliction> appliedAfflictions = null) { if (target == null || attacker == null) { return; } if (target == attacker) { return; } //damaging dead characters doesn't affect karma if (target.IsDead || target.Removed) { return; } bool isEnemy = target.AIController is EnemyAIController || target.TeamID != attacker.TeamID; if (GameMain.Server.TraitorManager?.Traitors != null) { if (GameMain.Server.TraitorManager.Traitors.Any(t => t.Character == target)) { //traitors always count as enemies isEnemy = true; } if (GameMain.Server.TraitorManager.Traitors.Any(t => t.Character == attacker && t.CurrentObjective != null && t.CurrentObjective.IsEnemy(target))) { //target counts as an enemy to the traitor isEnemy = true; } } bool targetIsHusk = target.CharacterHealth?.GetAffliction <AfflictionHusk>("huskinfection")?.State == AfflictionHusk.InfectionState.Active; bool attackerIsHusk = attacker.CharacterHealth?.GetAffliction <AfflictionHusk>("huskinfection")?.State == AfflictionHusk.InfectionState.Active; //huskified characters count as enemies to healthy characters and vice versa if (targetIsHusk != attackerIsHusk) { isEnemy = true; } if (appliedAfflictions != null) { foreach (Affliction affliction in appliedAfflictions) { if (MathUtils.NearlyEqual(affliction.Prefab.KarmaChangeOnApplied, 0.0f)) { continue; } damage -= affliction.Prefab.KarmaChangeOnApplied * affliction.Strength; } } Client targetClient = GameMain.Server.ConnectedClients.Find(c => c.Character == target); if (damage > 0 && targetClient != null) { var targetMemory = GetClientMemory(targetClient); targetMemory.LastAttackTime[attacker] = Timing.TotalTime; } Client attackerClient = GameMain.Server.ConnectedClients.Find(c => c.Character == attacker); ClientMemory attackerMemory = GetClientMemory(attackerClient); if (attackerMemory != null) { //if the attacker has been attacked by the target within the last x seconds, ignore the damage //(= no karma penalty from retaliating against someone who attacked you) if (attackerMemory.LastAttackTime.ContainsKey(target) && attackerMemory.LastAttackTime[target] > Timing.TotalTime - AllowedRetaliationTime) { damage = Math.Min(damage, 0); stun = 0.0f; } } //attacking/healing clowns has a smaller effect on karma if (target.HasEquippedItem("clownmask") && target.HasEquippedItem("clowncostume")) { damage *= 0.5f; stun *= 0.5f; } //smaller karma penalty for attacking someone who's aiming with a weapon if (damage > 0.0f && target.IsKeyDown(InputType.Aim) && target.SelectedItems.Any(it => it != null && (it.GetComponent <MeleeWeapon>() != null || it.GetComponent <RangedWeapon>() != null))) { damage *= 0.5f; stun *= 0.5f; } //damage scales according to the karma of the target //(= smaller karma penalty from attacking someone who has a low karma) if (damage > 0 && targetClient != null) { damage *= MathUtils.InverseLerp(0.0f, 50.0f, targetClient.Karma); } if (isEnemy) { if (damage > 0) { float karmaIncrease = damage * DamageEnemyKarmaIncrease; if (attacker?.Info?.Job.Prefab.Identifier == "securityofficer") { karmaIncrease *= 2.0f; } AdjustKarma(attacker, karmaIncrease, "Damaged enemy"); } } else { if (stun > 0 && attackerMemory != null) { //GameServer.Log(GameServer.CharacterLogName(attacker) + " stunned " + GameServer.CharacterLogName(target) + $" ({stun})", ServerLog.MessageType.Karma); attackerMemory.StunsInPastMinute.Add(new ClientMemory.TimeAmount() { Time = Timing.TotalTime, Amount = stun }); if (attackerMemory.StunsInPastMinute.Count > 1) { float avgStunsInflicted = attackerMemory.StunsInPastMinute[0].Amount / (float)(attackerMemory.StunsInPastMinute[1].Time - attackerMemory.StunsInPastMinute[0].Time); for (int i = 1; i < attackerMemory.StunsInPastMinute.Count; i++) { avgStunsInflicted += attackerMemory.StunsInPastMinute[i].Amount / (float)(attackerMemory.StunsInPastMinute[i].Time - attackerMemory.StunsInPastMinute[i - 1].Time); } //GameServer.Log(avgStunsInflicted.ToString(), ServerLog.MessageType.Karma); if (avgStunsInflicted > StunFriendlyKarmaDecreaseThreshold || attackerMemory.StunKarmaDecreaseMultiplier > 1.0f) { AdjustKarma(attacker, -StunFriendlyKarmaDecrease * attackerMemory.StunKarmaDecreaseMultiplier, "Stunned friendly"); attackerMemory.StunKarmaDecreaseMultiplier *= 2.0f; } } } if (damage > 0) { AdjustKarma(attacker, -damage * DamageFriendlyKarmaDecrease, "Damaged friendly"); } else { float karmaIncrease = -damage * HealFriendlyKarmaIncrease; if (attacker?.Info?.Job.Prefab.Identifier == "medicaldoctor") { karmaIncrease *= 2.0f; } AdjustKarma(attacker, karmaIncrease, "Healed friendly"); } } }