public static void HandleDecay(MapleClient c) { //ServerConsole.Info((DateTime.UtcNow.Ticks / TimeSpan.TicksPerMillisecond).ToString()); MapleCharacter chr = c.Account.Character; if (!chr.IsAran) { return; } AranSystem resource = (AranSystem)chr.Resource; if (resource.Combo > 1) { resource.Combo--; } Buff currentComboBuff = chr.GetBuff(Aran1.COMBO_ABILITY); if (currentComboBuff != null) { if (resource.Combo / 10 < currentComboBuff.Stacks / 10) { Buff newbuff = new Buff(Aran1.COMBO_ABILITY, currentComboBuff.Effect, SkillEffect.MAX_BUFF_TIME_MS, chr); newbuff.Stacks = resource.Combo; chr.GiveBuff(newbuff); } } }
public static void Handle(MapleClient c) { MapleCharacter chr = c.Account.Character; if (!chr.IsLuminous) { return; } int skillLevel = chr.GetSkillLevel(Luminous2.BLACK_BLESSING); if (skillLevel == 0) { return; } Buff buff = chr.GetBuff(Luminous2.BLACK_BLESSING); int orbAmount = 0; if (buff != null) { buff.CancelRemoveBuffSchedule(); orbAmount = buff.Stacks; } if (orbAmount < 3) { orbAmount += 1; } if (buff == null) { buff = new Buff(Luminous2.BLACK_BLESSING, DataBuffer.CharacterSkillBuffer[Luminous2.BLACK_BLESSING].GetEffect(1), SkillEffect.MAX_BUFF_TIME_MS, chr); chr.GiveBuff(buff); } else { Buff newbuff = new Buff(Luminous2.BLACK_BLESSING, buff.Effect, int.MaxValue, chr); newbuff.Stacks = orbAmount; chr.GiveBuff(newbuff); } }
public static bool HandleComboUsage(MapleCharacter chr, int comboCon) { AranSystem resource = (AranSystem)chr.Resource; if (resource.Combo < comboCon) { return(false); } else { resource.Combo -= comboCon; Buff currentComboBuff = chr.GetBuff(Aran1.COMBO_ABILITY); if (currentComboBuff != null) { if (resource.Combo / 10 < currentComboBuff.Stacks / 10) { Buff newbuff = new Buff(Aran1.COMBO_ABILITY, currentComboBuff.Effect, SkillEffect.MAX_BUFF_TIME_MS, chr); newbuff.Stacks = resource.Combo; chr.GiveBuff(newbuff); } } } return(true); }
private static void HandleAttackInfo(MapleClient c, AttackInfo attackInfo, SendHeader type, SkillEffect effect) { //Anti-cheat //c.CheatTracker.Trigger(AntiCheat.TriggerType.Attack); WzCharacterSkill wzSkill = effect != null ? effect.Parent : null; MapleCharacter chr = c.Account.Character; if (attackInfo.SkillId > 0) { if (!SkillEffect.CheckAndApplySkillEffect(c.Account.Character, attackInfo.SkillId, wzSkill, -1, attackInfo.Targets, attackInfo.Attacks)) { return; } } chr.Map.BroadcastPacket(GenerateAttackInfo(type, c.Account.Character, attackInfo), c.Account.Character, false); long totalDamage = 0; #region DoTs and Pickpocket int pickPocketProp = 0; int dotSkillId = 0; int dotChance = 0; int dotDamage = 0; int dotTimeMS = 0; int dotMaxStacks = 1; #region Thief if (chr.IsThief) { byte venomSkillLevel = 0; if (chr.IsBandit) { Buff pickPocket = chr.GetBuff(ChiefBandit.PICKPOCKET); if (pickPocket != null) { pickPocketProp = pickPocket.Effect.Info[CharacterSkillStat.prop]; } venomSkillLevel = chr.GetSkillLevel(ChiefBandit.VENOM); if (venomSkillLevel > 0) { dotSkillId = ChiefBandit.VENOM; byte toxicVenomSkillLevel = chr.GetSkillLevel(Shadower.TOXIC_VENOM); if (toxicVenomSkillLevel > 0) { venomSkillLevel = toxicVenomSkillLevel; dotSkillId = Shadower.TOXIC_VENOM; } } } else if (chr.IsAssassin) { #region Assassin venomSkillLevel = chr.GetSkillLevel(Hermit.VENOM); if (venomSkillLevel > 0) { dotSkillId = Hermit.VENOM; byte toxicVenomSkillLevel = chr.GetSkillLevel(NightLord.TOXIC_VENOM); if (toxicVenomSkillLevel > 0) { venomSkillLevel = toxicVenomSkillLevel; dotSkillId = NightLord.TOXIC_VENOM; } } #endregion } else if (chr.IsDualBlade) { #region DualBlade venomSkillLevel = chr.GetSkillLevel(DualBlade3.VENOM); if (venomSkillLevel > 0) { dotSkillId = DualBlade3.VENOM; byte toxicVenomSkillLevel = chr.GetSkillLevel(DualBlade4.TOXIC_VENOM); if (toxicVenomSkillLevel > 0) { venomSkillLevel = toxicVenomSkillLevel; dotSkillId = DualBlade4.TOXIC_VENOM; } } #endregion } if (venomSkillLevel > 0) { SkillEffect venomEffect = DataBuffer.GetCharacterSkillById(dotSkillId).GetEffect(venomSkillLevel); dotChance = venomEffect.Info[CharacterSkillStat.prop]; dotDamage = (int)(chr.Stats.GetDamage() * (venomEffect.Info[CharacterSkillStat.dot] / 100.0)); dotTimeMS = venomEffect.Info[CharacterSkillStat.dotTime] * 1000; if (!venomEffect.Info.TryGetValue(CharacterSkillStat.dotSuperpos, out dotMaxStacks)) { dotMaxStacks = 1; } } } #endregion if (attackInfo.SkillId > 0 && effect.Info.TryGetValue(CharacterSkillStat.dot, out dotDamage)) //Skill has/is dot { dotTimeMS = effect.Info[CharacterSkillStat.dotTime] * 1000; if (!effect.Info.TryGetValue(CharacterSkillStat.prop, out dotChance)) { dotChance = 100; } dotSkillId = attackInfo.SkillId; dotDamage = (int)(chr.Stats.GetDamage() * (dotDamage / 100.0)); if (!effect.Info.TryGetValue(CharacterSkillStat.dotSuperpos, out dotMaxStacks)) { dotMaxStacks = 1; } } #endregion foreach (AttackPair ap in attackInfo.TargetDamageList) { MapleMonster mob = chr.Map.GetMob(ap.TargetObjectId); if (mob != null && mob.Alive) { long totalMobDamage = 0; foreach (int damage in ap.Damage) { totalMobDamage += damage; } if (totalMobDamage > 0) { totalDamage += totalMobDamage; if (totalDamage > int.MaxValue) { totalDamage = int.MaxValue; } #region Status effects if (effect != null) { foreach (MonsterBuffApplication mba in effect.MonsterBuffs) { if (Functions.MakeChance(mba.Prop)) { foreach (var kvp in mba.Buffs) { mob.ApplyStatusEffect(attackInfo.SkillId, kvp.Key, kvp.Value, mba.Duration, chr); } } } } #endregion #region MP Eater if (chr.Stats.MpEaterProp > 0) { if (Functions.MakeChance(chr.Stats.MpEaterProp)) { int mpSteal = (int)((chr.Stats.MpEaterR / 100.0) * mob.WzInfo.MP); chr.AddMP(mpSteal); } } #endregion #region Bandit if (chr.IsBandit) { if (Functions.MakeChance(pickPocketProp)) { chr.Map.SpawnMesoMapItem(1, mob.Position, chr.Map.GetDropPositionBelow(mob.Position, mob.Position), false, MapleDropType.Player, chr); } if (attackInfo.SkillId == Bandit.STEAL) { int prop = DataBuffer.GetCharacterSkillById(Bandit.STEAL).GetEffect(chr.GetSkillLevel(Bandit.STEAL)).Info[CharacterSkillStat.prop]; if (Functions.MakeChance(prop)) { MapleItem item = mob.TryGetStealableItem(chr.Id, chr.Name); if (item != null) { chr.Map.SpawnMapItem(item, mob.Position, chr.Map.GetDropPositionBelow(chr.Position, mob.Position), false, Map.MapleDropType.Player, chr); } } } } #endregion if (Functions.MakeChance(dotChance)) { mob.ApplyPoison(dotSkillId, dotTimeMS, dotDamage, 1000, chr, dotMaxStacks); } mob.Damage(chr, (int)totalDamage); } } } #region special skill handling if (type == SendHeader.RangedAttack) { if (attackInfo.Targets > 0 && chr.IsHunter) { #region QuiverCartridge QuiverCartridgeSystem qcs = chr.Resource as QuiverCartridgeSystem; if (qcs != null && qcs.ChosenArrow > -1) { int usedArrow = qcs.HandleUse(c); switch (usedArrow) { case 0: // Blood if (Functions.MakeChance(50)) //50% chance to heal 20% of damage as hp { chr.AddHP((int)(totalDamage * 0.2)); } break; case 1: // Poison //TODO: poison, 90% damage, 8 seconds, stacks 3 times break; case 2: // Magic, don't need handling I think break; } } #endregion } } if (totalDamage > 0) { BuffedCharacterStats stats = chr.Stats; if (stats.LifeStealProp > 0 && stats.LifeStealR > 0) { if (Functions.MakeChance(stats.LifeStealProp)) { int lifesteal = (int)((stats.LifeStealR / 100.0) * totalDamage); chr.AddHP(lifesteal); } } if (chr.IsMagician) { #region ArcaneAim int arcaneAimId = 0; if (chr.Job == JobConstants.FIREPOISON4) { arcaneAimId = FirePoison4.ARCANE_AIM; } else if (chr.Job == JobConstants.ICELIGHTNING4) { arcaneAimId = IceLightning4.ARCANE_AIM; } else if (chr.Job == JobConstants.BISHOP) { arcaneAimId = Bishop.ARCANE_AIM; } if (arcaneAimId > 0) { byte skillLevel = chr.GetSkillLevel(arcaneAimId); if (skillLevel > 0) { if ((DateTime.UtcNow.Subtract(chr.LastAttackTime).TotalMilliseconds) < 5000) { Buff oldBuff = chr.GetBuff(arcaneAimId); if (oldBuff != null) { int prop = oldBuff.Effect.Info[CharacterSkillStat.prop]; if (Functions.MakeChance(prop)) { Buff newBuff = new Buff(arcaneAimId, oldBuff.Effect, oldBuff.Duration, chr); int oldStacks = oldBuff.Stacks / 6; newBuff.Stacks = Math.Min(30, (oldStacks + 1) * 6); chr.GiveBuff(newBuff); } } else { SkillEffect arcaneAimEffect = DataBuffer.GetCharacterSkillById(arcaneAimId).GetEffect(skillLevel); int prop = arcaneAimEffect.Info[CharacterSkillStat.prop]; if (Functions.MakeChance(prop)) { Buff newBuff = new Buff(arcaneAimId, arcaneAimEffect, 5000, chr); newBuff.Stacks = 6; chr.GiveBuff(newBuff); } } } } } #endregion } else if (chr.IsThief) { if (chr.IsBandit) { chr.IncreaseCriticalGrowth(true); byte skillLevel = chr.GetSkillLevel(Shadower.SHADOWER_INSTINCT); if (skillLevel > 0) { ((BodyCountSystem)chr.Resource).IncreaseBodyCount(c); } } } } #endregion chr.LastAttackTime = DateTime.UtcNow; }
private static int DoMonsterDamageModifiers(int damage, MapleCharacter chr, MapleMonster mobFrom, int mobFromOID) { if (damage == 0) //guard/miss etc { Buff buff = chr.GetBuff(Priest.HOLY_MAGIC_SHELL); if (buff != null) { buff.Stacks -= 1; if (buff.Stacks == 0) { chr.CancelBuff(Priest.HOLY_MAGIC_SHELL); } } } #region Spearman if (chr.IsSpearman) { if (chr.Job >= JobConstants.BERSERKER) { if (chr.Job == JobConstants.DARKKNIGHT) { byte evilEyeRevengeLevel = chr.GetSkillLevel(DarkKnight.REVENGE_OF_THE_EVIL_EYE); if (evilEyeRevengeLevel > 0 && !chr.HasSkillOnCooldown(DarkKnight.REVENGE_OF_THE_EVIL_EYE)) { MapleSummon evilEye = chr.GetSummon(Spearman.EVIL_EYE); Buff evilEyebuff = chr.GetBuff(Spearman.EVIL_EYE); if (evilEye != null && evilEyebuff != null && evilEyebuff.Stacks != Berserker.EVIL_EYE_OF_DOMINATION) { SkillEffect effect = DataBuffer.GetCharacterSkillById(DarkKnight.REVENGE_OF_THE_EVIL_EYE).GetEffect(evilEyeRevengeLevel); int summonDamage = (int)((effect.Info[CharacterSkillStat.damage] / 100.0) * chr.Stats.GetDamage()); int healHp = (int)((effect.Info[CharacterSkillStat.x] / 100.0) * summonDamage); chr.AddHP(healHp); //instant KO: if (!mobFrom.IsBoss && summonDamage < mobFrom.HP) { if (Functions.MakeChance(effect.Info[CharacterSkillStat.z])) { summonDamage = mobFrom.HP; } } evilEye.AttackMonster(summonDamage, 0x84, mobFrom); chr.AddCooldownSilent(DarkKnight.REVENGE_OF_THE_EVIL_EYE, (uint)effect.Info[CharacterSkillStat.cooltime] * 1000, DateTime.UtcNow, false); } } if (chr.HasBuff(DarkKnight.FINAL_PACT2)) { return(0); //Invincible } } Buff crossSurgeBuff = chr.GetBuff(Berserker.CROSS_SURGE); if (crossSurgeBuff != null) { int absorbPercent = crossSurgeBuff.Effect.Info[CharacterSkillStat.y]; int absorb = (int)((chr.Stats.MaxHp - chr.Hp) * (absorbPercent / 100.0)); absorb = Math.Min(absorb, crossSurgeBuff.Effect.Info[CharacterSkillStat.z]); //normally z = 4000 damage -= absorb; } } } #endregion #region Magician else if (chr.IsMagician) { Buff buff = chr.GetBuff(Magician.MAGIC_GUARD); if (buff != null) { if (chr.Mp > 0) { int absorb = (int)((buff.Effect.Info[CharacterSkillStat.x] / 100.0) * damage); if (chr.Mp < absorb) { absorb = chr.Mp; } chr.AddMP(-absorb); damage -= absorb; } } } #endregion #region Bandit else if (chr.IsBandit) { Buff mesoGuard = chr.GetBuff(Bandit.MESOGUARD); if (mesoGuard != null) { double absorb = 0.5; double mesoLoss = mesoGuard.Effect.Info[CharacterSkillStat.x] / 100.0; double mesoLossReduction = 0.0; byte MesoMasteryLevel = chr.GetSkillLevel(ChiefBandit.MESO_MASTERY); if (MesoMasteryLevel > 0) { SkillEffect effect = DataBuffer.GetCharacterSkillById(ChiefBandit.MESO_MASTERY).GetEffect(MesoMasteryLevel); absorb += effect.Info[CharacterSkillStat.v] / 100.0; mesoLossReduction = effect.Info[CharacterSkillStat.v] / 100.0; } int damageAbsorbed = (int)(damage * absorb); if (damageAbsorbed > 0) { int mesoUse = (int)(damageAbsorbed * mesoLoss); mesoUse -= (int)(mesoUse * mesoLossReduction); if (chr.Mesos >= mesoUse) { chr.Inventory.RemoveMesos(mesoUse, false); damage -= damageAbsorbed; int mesoDrops = Functions.Random(1, 4); for (int i = 0; i < mesoDrops; i++) { chr.Map.SpawnMesoMapItem(1, chr.Position, chr.Map.GetDropPositionBelow(chr.Position, chr.Position), false, MapleDropType.Player, chr); } } } } } #endregion #region Luminous else if (chr.IsLuminous) { Buff oldBuff = chr.GetBuff(Luminous2.BLACK_BLESSING); if (oldBuff != null) { int remove = (int)(damage * 0.7); damage -= remove; if (oldBuff.Stacks < 2) { chr.CancelBuff(Luminous2.BLACK_BLESSING); } else { chr.CancelBuffSilent(Luminous2.BLACK_BLESSING); Buff newBuff = new Buff(oldBuff.SkillId, oldBuff.Effect, oldBuff.Duration, chr); newBuff.Stacks = oldBuff.Stacks - 1; chr.GiveBuff(newBuff); } } byte skillLevel = 0; if ((skillLevel = chr.GetSkillLevel(Luminous1.STANDARD_MAGIC_GUARD)) > 0) { SkillEffect effect = DataBuffer.GetCharacterSkillById(Luminous1.STANDARD_MAGIC_GUARD).GetEffect(skillLevel); double percent = effect.Info[CharacterSkillStat.x] / 100.0; int absorb = (int)(percent * damage); if (chr.Mp >= absorb) { chr.AddMP(absorb); damage -= absorb; } } } #endregion return(damage); }
public void Kill(MapleCharacter killer, bool dropItems = true) { lock (MobLock) { //killer.Client.CheatTracker.KillTrigger(this); Alive = false; int exp = WzInfo.Exp * ServerConstants.ExpRate; MapleCharacter dropOwner = killer; int HighestExp = 0; foreach (KeyValuePair <int, long> kvp in AttackerDamageList) { MapleCharacter attacker = Map.GetCharacter(kvp.Key); if (attacker != null) { double expPercent = ((double)Math.Min(kvp.Value, WzInfo.HP) / (double)WzInfo.HP); int expToGive = (int)((expPercent * exp) * (attacker.Stats.ExpR / 100.0)); //Drops go to the person who did the most damage if (expToGive > HighestExp) { HighestExp = expToGive; dropOwner = attacker; } attacker.GainExp(expToGive, true, true); } } if (dropItems) { Map.SpawnMapItemsFromMonster(this, this.Position, dropOwner); } dropOwner.UpdateQuestKills(WzInfo.MobId); //TODO: whole party on map Map.BroadcastPacket(MapleMonster.KillMob(ObjectId)); Map.RemoveMob(ObjectId); #region Final Pact if (dropOwner.Job == JobConstants.DARKKNIGHT) { Buff buff = dropOwner.GetBuff(DarkKnight.FINAL_PACT2); if (buff != null) { buff.Stacks--; if (buff.Stacks <= 0) { dropOwner.Client.SendPacket(Skill.ShowBuffEffect(DarkKnight.FINAL_PACT2, dropOwner.Level, null, false)); dropOwner.CancelBuff(DarkKnight.FINAL_PACT2); } else { uint remainingTimeMS = buff.Duration - (uint)DateTime.UtcNow.Subtract(buff.StartTime).TotalMilliseconds; dropOwner.Client.SendPacket(Buff.UpdateFinalPactKillCount(buff.Stacks, remainingTimeMS)); } } } #endregion Map = null; foreach (MonsterBuff effect in Buffs) { effect.Dispose(true); } } }
public static bool CheckAndApplySkillEffect(MapleCharacter chr, int skillId, WzCharacterSkill wzCharacterSkill, int skillLevel = -1, int numTargets = 0, int numAttacks = 0) { if (skillLevel == -1) { skillLevel = chr.GetSkillLevel(skillId); } if (wzCharacterSkill == null) { wzCharacterSkill = DataBuffer.GetCharacterSkillById(skillId); if (wzCharacterSkill == null) { return(false); } } if (wzCharacterSkill.HasFixedLevel && JobConstants.JobCanLearnSkill(skillId, chr.Job)) { skillLevel = 1; } if (chr.IsPhantom) //check stolen skill level { PhantomSystem resource = (PhantomSystem)chr.Resource; int chosenSkillIndex = resource.GetChosenSkillIndex(skillId); if (chosenSkillIndex > -1) { int impeccableMemory = PhantomSystem.GetStealSkill(chosenSkillIndex + 1); skillLevel = Math.Min(chr.GetSkillLevel(impeccableMemory), chr.GetSkillLevel(skillId)); } } if (skillLevel == 0 || (chr.HasSkillOnCooldown(skillId))) { string text = "Player tried using skill " + skillId + " while level 0 or on cooldown."; ServerConsole.Warning(text); FileLogging.Log("./LinkedSkills.txt", text); return(false); } SkillEffect effect = wzCharacterSkill.GetEffect((byte)skillLevel); if (effect == null) { return(false); } bool shadowPartner = false; if (numTargets > 0) { int attackCount = effect.AttackCount; if (chr.IsLuminous || (chr.IsBandit && chr.HasBuff(ChiefBandit.SHADOW_PARTNER)) || (chr.IsAssassin && chr.HasBuff(Hermit.SHADOW_PARTNER)) || (chr.IsNightWalker && chr.HasBuff(NightWalker3.SHADOW_PARTNER))) { attackCount *= 2; shadowPartner = true; } if (effect.MobCount < numTargets || attackCount < numAttacks) { return(false); } } int bulletConsume; if (effect.Info.TryGetValue(CharacterSkillStat.bulletConsume, out bulletConsume)) { if (shadowPartner) { bulletConsume *= 2; } if (!DealDamageHandler.HandleRangedAttackAmmoUsage(chr, bulletConsume)) { ServerConsole.Warning("Character with job: " + chr.Job + " tried using a skill with bulletCount: " + bulletConsume + " but doesn't have the bullets!"); return(false); } } if (chr.Mp < effect.MpCon) { return(false); } else { chr.AddMP(-effect.MpCon); } int hpCon; if (effect.Info.TryGetValue(CharacterSkillStat.hpCon, out hpCon)) { if (chr.Hp < hpCon) { return(false); } chr.AddHP(-hpCon); } #region Manual skill handlers and checks if (chr.IsAran && effect.Info.ContainsKey(CharacterSkillStat.aranComboCon)) { if (!AranSystem.HandleComboUsage(chr, effect.Info[CharacterSkillStat.aranComboCon])) { return(false); } } else if (chr.IsLuminous && chr.Job >= JobConstants.LUMINOUS2 && effect.Info.ContainsKey(CharacterSkillStat.gauge)) { LuminousSystem.HandleGaugeGain(chr, skillId, effect.Info[CharacterSkillStat.gauge]); } switch (skillId) { case Berserker.EVIL_EYE_OF_DOMINATION: { Buff evilEyeBuff = chr.GetBuff(Spearman.EVIL_EYE); MapleSummon evilEye = chr.GetSummon(Spearman.EVIL_EYE); if (evilEyeBuff == null || evilEye == null) { return(false); } uint timeUsed = (uint)((DateTime.UtcNow.Subtract(evilEyeBuff.StartTime)).TotalMilliseconds); uint timeRemainingMS = (uint)evilEyeBuff.Duration - timeUsed; Buff newBuff = new Buff(Spearman.EVIL_EYE, effect, timeRemainingMS, chr); if (evilEyeBuff.Stacks == Berserker.EVIL_EYE_OF_DOMINATION) { newBuff.Stacks = Spearman.EVIL_EYE; evilEye.MovementType = SummonMovementType.Follow; } else { newBuff.Stacks = Berserker.EVIL_EYE_OF_DOMINATION; evilEye.MovementType = SummonMovementType.CircleFollow; } chr.GiveBuff(newBuff); return(true); //no other actions needed } case Berserker.EVIL_EYE_SHOCK: { MapleSummon evilEye = chr.GetSummon(Spearman.EVIL_EYE); if (evilEye == null) { return(false); } List <MapleMonster> mobs = chr.Map.GetMobsInRange(new BoundingBox(evilEye.Position, wzCharacterSkill.TopLeft, wzCharacterSkill.BottomRight)); if (mobs.Count > 0) { int damage = (int)((effect.Info[CharacterSkillStat.damage] / 100.0) * chr.Stats.GetDamage()); int stunProp = effect.Info[CharacterSkillStat.prop]; int stunTime = effect.Info[CharacterSkillStat.time] * 1000; int mobCounter = 0; foreach (MapleMonster mob in mobs) { mob.Damage(chr, damage); if (mob.Alive) { if (Functions.MakeChance(stunProp)) { mob.ApplyStatusEffect(skillId, MonsterBuffStat.STUN, 1, stunTime, chr); } } mobCounter++; if (mobCounter == 10) { break; } } } break; } case DarkKnight.SACRIFICE: if (!chr.RemoveSummon(Spearman.EVIL_EYE)) { return(false); } chr.CancelBuff(Spearman.EVIL_EYE); int healHpR = effect.Info[CharacterSkillStat.y]; int heal = (int)((healHpR / 100.0) * chr.Stats.MaxHp); chr.AddHP(heal); break; case LuminousBasics.SUNFIRE: case LuminousBasics.ECLIPSE: case LuminousBasics.EQUILIBRIUM2: LuminousSystem.HandleChangeDarkLight(chr, skillId); break; } #endregion #region Apply Cooldown bool skipCooldown = skillId == DarkKnight.GUNGNIRS_DESCENT && (chr.HasBuff(DarkKnight.SACRIFICE) || chr.HasBuff(DarkKnight.FINAL_PACT2)); if (!skipCooldown) { int coolTime; if (effect.Info.TryGetValue(CharacterSkillStat.cooltime, out coolTime) && coolTime > 0) { chr.AddCooldown(skillId, (uint)coolTime * 1000); //time in the wz is in seconds } } #endregion effect.ApplyEffect(chr, chr); if (wzCharacterSkill.IsBuff) { effect.ApplyBuffEffect(chr); chr.Map.BroadcastPacket(SkillEffect.Packets.ShowForeignSkillEffect(chr.Id, chr.Level, skillId, effect.Level), chr); } if (wzCharacterSkill.IsPartySkill) { if (chr.Party != null) { List <MapleCharacter> partyMembersOnSameMap = chr.Party.GetCharactersOnMap(chr.Map, chr.Id); if (partyMembersOnSameMap.Count > 0) { List <MapleCharacter> partyMembersInRange = chr.Map.GetCharactersInRange(effect.CalculateBoundingBox(chr.Position, chr.IsFacingLeft), partyMembersOnSameMap); foreach (MapleCharacter partyMember in partyMembersInRange) { effect.ApplyEffect(chr, partyMember); if (wzCharacterSkill.IsBuff) { effect.ApplyBuffEffect(partyMember); } } } } else if (wzCharacterSkill.IsGmSkill && chr.IsStaff) { var targets = chr.Map.GetCharactersInRange(effect.CalculateBoundingBox(chr.Position, chr.IsFacingLeft)); foreach (MapleCharacter target in targets.Where(x => x.Id != chr.Id)) { effect.ApplyEffect(chr, target); if (wzCharacterSkill.IsBuff) { effect.ApplyBuffEffect(target); } } } } return(true); }