//Calculates bonus EXP for Links and Chains public static void AddBattleBonusEXP(Player attacker, BattleNpc defender, CommandResultContainer actionContainer) { ushort baseExp = GetBaseEXP(attacker, defender); //Only bother calculating the rest if there's actually exp to be gained. //0 exp sends no message if (baseExp > 0) { int totalBonus = 0;//GetMod(Modifier.bonusEXP) var linkCount = defender.GetMobMod(MobModifier.LinkCount); totalBonus += GetLinkBonus((byte)Math.Min(linkCount, 255)); StatusEffect effect = attacker.statusEffects.GetStatusEffectById((uint)StatusEffectId.EXPChain); ushort expChainNumber = 0; uint timeLimit = 100; if (effect != null) { expChainNumber = effect.GetTier(); timeLimit = (uint)(GetChainTimeLimit(expChainNumber)); actionContainer?.AddEXPAction(new CommandResult(attacker.actorId, 33919, 0, expChainNumber, (byte)timeLimit)); } totalBonus += GetChainBonus(expChainNumber); StatusEffect newChain = Server.GetWorldManager().GetStatusEffect((uint)StatusEffectId.EXPChain); newChain.SetSilent(true); newChain.SetDuration(timeLimit); newChain.SetTier((byte)(Math.Min(expChainNumber + 1, 255))); attacker.statusEffects.AddStatusEffect(newChain, attacker, true, true); actionContainer?.AddEXPActions(attacker.AddExp(baseExp, (byte)attacker.GetClass(), (byte)(totalBonus.Min(255)))); } }
public override void Die(DateTime tick, CommandResultContainer actionContainer = null) { if (IsAlive()) { // todo: does retail if (lastAttacker is Pet && lastAttacker.aiContainer.GetController <PetController>() != null && lastAttacker.aiContainer.GetController <PetController>().GetPetMaster() is Player) { lastAttacker = lastAttacker.aiContainer.GetController <PetController>().GetPetMaster(); } if (lastAttacker is Player) { //I think this is, or should be odne in DoBattleAction. Packet capture had the message in the same packet as an attack // <actor> defeat/defeats <target> if (actionContainer != null) { actionContainer.AddEXPAction(new CommandResult(actorId, 30108, 0)); } if (lastAttacker.currentParty != null && lastAttacker.currentParty is Party) { foreach (var memberId in ((Party)lastAttacker.currentParty).members) { var partyMember = zone.FindActorInArea <Character>(memberId); // onDeath(monster, player, killer) lua.LuaEngine.CallLuaBattleFunction(this, "onDeath", this, partyMember, lastAttacker); // todo: add actual experience calculation and exp bonus values. if (partyMember is Player) { BattleUtils.AddBattleBonusEXP((Player)partyMember, this, actionContainer); } } } else { // onDeath(monster, player, killer) lua.LuaEngine.CallLuaBattleFunction(this, "onDeath", this, lastAttacker, lastAttacker); //((Player)lastAttacker).QueuePacket(BattleActionX01Packet.BuildPacket(lastAttacker.actorId, 0, 0, new BattleAction(actorId, 30108, 0))); } } if (positionUpdates != null) { positionUpdates.Clear(); } aiContainer.InternalDie(tick, despawnTime); //this.ResetMoveSpeeds(); // todo: reset cooldowns lua.LuaEngine.GetInstance().OnSignal("mobkill"); } else { var err = String.Format("[{0}][{1}] {2} {3} {4} {5} tried to die ded", actorId, GetUniqueId(), positionX, positionY, positionZ, GetZone().GetName()); Program.Log.Error(err); //throw new Exception(err); } }