public static void Low(string[] split, MapleClient c) { MapleCharacter chr = c.Account.Character; chr.AddHP((-chr.Hp) + 1); chr.AddMP((-chr.Mp) + 1); }
public static void Handle(MapleClient c, PacketReader pr) { int tickCount = pr.ReadInt(); short slot = pr.ReadShort(); int id = pr.ReadInt(); MapleCharacter chr = c.Account.Character; MapleItem item = chr.Inventory.GetItemSlotFromInventory(MapleInventoryType.Use, slot); if (item != null && item.ItemId == id) { WzConsume consume = DataBuffer.GetItemById(id) as WzConsume; if (consume != null) { chr.Inventory.RemoveItemsFromSlot(MapleInventoryType.Use, slot, 1, true); if (!chr.Map.PotionLimit) { if (consume.Hp != 0) { chr.AddHP((int)((chr.Stats.PotionEffectR / 100.0) * consume.Hp)); } if (consume.Mp != 0) { chr.AddMP((int)((chr.Stats.PotionEffectR / 100.0) * consume.Mp)); } if (consume.HpR != 0) { chr.AddHP((int)(chr.Stats.MaxHp * (consume.HpR / 100.0))); } if (consume.MpR != 0) { chr.AddMP((int)(chr.Stats.MaxMp * (consume.MpR / 100.0))); } } if (consume.MoveTo != 0 && !chr.Map.PortalScrollLimit) { chr.ChangeMap(consume.MoveTo); } if (consume.CharismaExp != 0) { chr.AddTraitExp(consume.CharismaExp, MapleCharacterStat.Charisma); } if (consume.CharmExp != 0) { chr.AddTraitExp(consume.CharmExp, MapleCharacterStat.Charm); } if (consume.CraftExp != 0) { chr.AddTraitExp(consume.CraftExp, MapleCharacterStat.Craft); } if (consume.InsightExp != 0) { chr.AddTraitExp(consume.InsightExp, MapleCharacterStat.Insight); } if (consume.SenseExp != 0) { chr.AddTraitExp(consume.SenseExp, MapleCharacterStat.Sense); } if (consume.WillExp != 0) { chr.AddTraitExp(consume.WillExp, MapleCharacterStat.Will); } return; } } chr.EnableActions(); }
public void Recalculate(MapleCharacter chr) { int mhpX = 0, mmpX = 0; int mhpR = 0, mmpR = 0; int lv2mhp = 0, lv2mmp = 0; int strR = 0, dexR = 0, intR = 0, lukR = 0; int watk = 0, matk = 9; int damR = 100, pdR = 0; Str = chr.Str + 5; Dex = chr.Dex + 5; Int = chr.Int + 5; Luk = chr.Luk + 5; MinDamage = 0; MaxDamage = 0; AsrR = 0; RecoveryHp = 0; RecoveryMp = 0; RecoveryHpR = 0; RecoveryMpR = 0; RecoveryTime = 0; watk = 3; matk = 3; LifeStealR = 0; LifeStealProp = 0; MpEaterR = 0; MpEaterProp = 0; DoTTimeInc = 0; CostMpR = 0; ExpR = 100; MesoR = 100; DropR = 100; PickPocketR = 0; StunR = 0; AmmoInc = 0; MasteryR = 0; BuffTimeR = 100; PotionEffectR = 100; ElixirEffectR = 100; CritRate = 5; ExpLossReductionR = 0; #region PassiveSkills IEnumerable <Skill> passiveSkills = chr.GetSkillList().Where(x => x.SkillId % 10000 < 1000); foreach (Skill skill in passiveSkills) { if (skill.Level < 1) { continue; } WzCharacterSkill skillInfo = DataBuffer.GetCharacterSkillById(skill.SkillId); if (skillInfo == null) { continue; } SkillEffect effect = skillInfo.GetEffect(skill.Level); if (effect == null) { continue; } foreach (var kvp in effect.Info) { switch (kvp.Key) { case CharacterSkillStat.mhpX: mhpX += kvp.Value; break; case CharacterSkillStat.mmpX: mmpX += kvp.Value; break; case CharacterSkillStat.mhpR: mhpR += kvp.Value; break; case CharacterSkillStat.mmpR: mmpR += kvp.Value; break; case CharacterSkillStat.lv2mhp: lv2mhp += kvp.Value; break; case CharacterSkillStat.lv2mmp: lv2mmp += kvp.Value; break; case CharacterSkillStat.strX: Str += kvp.Value; break; case CharacterSkillStat.dexX: Dex += kvp.Value; break; case CharacterSkillStat.intX: Int += kvp.Value; break; case CharacterSkillStat.lukX: Luk += kvp.Value; break; case CharacterSkillStat.asrR: AsrR += kvp.Value; break; case CharacterSkillStat.mastery: MasteryR = Math.Max(MasteryR, kvp.Value); break; case CharacterSkillStat.costmpR: CostMpR += kvp.Value; break; case CharacterSkillStat.bufftimeR: BuffTimeR += kvp.Value; break; case CharacterSkillStat.padX: watk += kvp.Value; break; case CharacterSkillStat.madX: matk += kvp.Value; break; case CharacterSkillStat.pdR: pdR += kvp.Value; break; case CharacterSkillStat.damR: damR += kvp.Value; break; case CharacterSkillStat.cr: CritRate += kvp.Value; break; } } } #region Specific passive skill handling byte skillLevel; if (chr.IsWarrior) { if ((skillLevel = chr.GetSkillLevel(Swordman.IRON_BODY)) > 0) { mhpR += DataBuffer.CharacterSkillBuffer[Swordman.IRON_BODY].GetEffect(skillLevel).Info[CharacterSkillStat.mhpR]; } if (chr.IsFighter) { if ((skillLevel = chr.GetSkillLevel(Crusader.SELF_RECOVERY)) > 0) { var info = DataBuffer.CharacterSkillBuffer[Crusader.SELF_RECOVERY].GetEffect(skillLevel).Info; RecoveryHp += info[CharacterSkillStat.hp]; RecoveryMp += info[CharacterSkillStat.mp]; } } else if (chr.IsSpearman) { if ((skillLevel = chr.GetSkillLevel(Berserker.LORD_OF_DARKNESS)) > 0) { var info = DataBuffer.CharacterSkillBuffer[Berserker.LORD_OF_DARKNESS].GetEffect(skillLevel).Info; LifeStealProp += info[CharacterSkillStat.prop]; LifeStealR += info[CharacterSkillStat.x]; } } } else if (chr.IsMagician) { if (chr.IsFirePoisonMage) { if ((skillLevel = chr.GetSkillLevel(FirePoison2.SPELL_MASTERY)) > 0) { matk += DataBuffer.CharacterSkillBuffer[FirePoison2.SPELL_MASTERY].GetEffect(skillLevel).Info[CharacterSkillStat.x]; } if ((skillLevel = chr.GetSkillLevel(FirePoison2.MP_EATER)) > 0) { var info = DataBuffer.CharacterSkillBuffer[FirePoison2.MP_EATER].GetEffect(skillLevel).Info; MpEaterProp += info[CharacterSkillStat.prop]; MpEaterR += info[CharacterSkillStat.x]; } } if (chr.IsIceLightningMage) { if ((skillLevel = chr.GetSkillLevel(IceLightning2.MP_EATER)) > 0) { var info = DataBuffer.CharacterSkillBuffer[IceLightning2.MP_EATER].GetEffect(skillLevel).Info; MpEaterProp += info[CharacterSkillStat.prop]; MpEaterR += info[CharacterSkillStat.x]; } if ((skillLevel = chr.GetSkillLevel(IceLightning2.SPELL_MASTERY)) > 0) { matk += DataBuffer.CharacterSkillBuffer[IceLightning2.SPELL_MASTERY].GetEffect(skillLevel).Info[CharacterSkillStat.x]; } } if (chr.IsCleric) { if ((skillLevel = chr.GetSkillLevel(Cleric.MP_EATER)) > 0) { var info = DataBuffer.CharacterSkillBuffer[Cleric.MP_EATER].GetEffect(skillLevel).Info; MpEaterProp += info[CharacterSkillStat.prop]; MpEaterR += info[CharacterSkillStat.x]; } if ((skillLevel = chr.GetSkillLevel(Cleric.SPELL_MASTERY)) > 0) { matk += DataBuffer.CharacterSkillBuffer[Cleric.SPELL_MASTERY].GetEffect(skillLevel).Info[CharacterSkillStat.x]; } if ((skillLevel = chr.GetSkillLevel(Priest.DIVINE_PROTECTION)) > 0) { AsrR += DataBuffer.CharacterSkillBuffer[Priest.DIVINE_PROTECTION].GetEffect(skillLevel).Info[CharacterSkillStat.asrR]; } } } else if (chr.IsArcher) { if (chr.IsHunter) { if ((skillLevel = chr.GetSkillLevel(Bowmaster.BOW_EXPERT)) > 0) { watk += DataBuffer.CharacterSkillBuffer[Bowmaster.BOW_EXPERT].GetEffect(skillLevel).Info[CharacterSkillStat.x]; } } else if (chr.IsCrossbowman) { if ((skillLevel = chr.GetSkillLevel(Marksman.CROSSBOW_EXPERT)) > 0) { watk += DataBuffer.CharacterSkillBuffer[Marksman.CROSSBOW_EXPERT].GetEffect(skillLevel).Info[CharacterSkillStat.x]; } } } else if (chr.IsThief) { if (chr.IsAssassin) { if ((skillLevel = chr.GetSkillLevel(Assassin.CLAW_MASTERY)) > 0) { AmmoInc += DataBuffer.CharacterSkillBuffer[Assassin.CLAW_MASTERY].GetEffect(skillLevel).Info[CharacterSkillStat.y]; } if ((skillLevel = chr.GetSkillLevel(Hermit.ALCHEMIC_ADRENALINE)) > 0) { PotionEffectR += DataBuffer.CharacterSkillBuffer[Hermit.ALCHEMIC_ADRENALINE].GetEffect(skillLevel).Info[CharacterSkillStat.x] - 100; } if ((skillLevel = chr.GetSkillLevel(NightLord.CLAW_EXPERT)) > 0) { watk += DataBuffer.CharacterSkillBuffer[NightLord.CLAW_EXPERT].GetEffect(skillLevel).Info[CharacterSkillStat.x]; } } else if (chr.IsBandit) { if ((skillLevel = chr.GetSkillLevel(Bandit.SHIELD_MASTERY)) > 0) { watk += DataBuffer.CharacterSkillBuffer[Bandit.SHIELD_MASTERY].GetEffect(skillLevel).Info[CharacterSkillStat.y]; } if ((skillLevel = chr.GetSkillLevel(ChiefBandit.MESO_MASTERY)) > 0) { var info = DataBuffer.CharacterSkillBuffer[ChiefBandit.MESO_MASTERY].GetEffect(skillLevel).Info; MesoR += info[CharacterSkillStat.mesoR]; PickPocketR += info[CharacterSkillStat.u]; } if ((skillLevel = chr.GetSkillLevel(Shadower.DAGGER_EXPERT)) > 0) { watk += DataBuffer.CharacterSkillBuffer[Shadower.DAGGER_EXPERT].GetEffect(skillLevel).Info[CharacterSkillStat.x]; } } } else if (chr.IsDualBlade) { if ((skillLevel = chr.GetSkillLevel(DualBlade3p.LIFE_DRAIN)) > 0) { var info = DataBuffer.CharacterSkillBuffer[DualBlade3p.LIFE_DRAIN].GetEffect(skillLevel).Info; LifeStealR += info[CharacterSkillStat.x]; LifeStealProp += info[CharacterSkillStat.prop]; } if ((skillLevel = chr.GetSkillLevel(DualBlade4.KATARA_EXPERT)) > 0) { watk += DataBuffer.CharacterSkillBuffer[DualBlade4.KATARA_EXPERT].GetEffect(skillLevel).Info[CharacterSkillStat.x]; } } else if (chr.IsPirate) { if (chr.IsBrawler) { if ((skillLevel = chr.GetSkillLevel(Brawler.PERSEVERANCE)) > 0) { var info = DataBuffer.CharacterSkillBuffer[Brawler.PERSEVERANCE].GetEffect(skillLevel).Info; int x = info[CharacterSkillStat.x]; RecoveryHpR += x; RecoveryMpR += x; RecoveryTime = info[CharacterSkillStat.y]; } if ((skillLevel = chr.GetSkillLevel(Marauder.STUN_MASTERY)) > 0) { StunR += DataBuffer.CharacterSkillBuffer[Marauder.STUN_MASTERY].GetEffect(skillLevel).Info[CharacterSkillStat.subProp]; } } else if (chr.IsGunslinger) { if ((skillLevel = skillLevel = chr.GetSkillLevel(Gunslinger.GUN_MASTERY)) > 0) { AmmoInc += DataBuffer.CharacterSkillBuffer[Gunslinger.GUN_MASTERY].GetEffect(skillLevel).Info[CharacterSkillStat.y]; } } } else if (chr.IsCannonneer) { if ((skillLevel = chr.GetSkillLevel(Cannoneer3.BARREL_ROULETTE)) > 0) { damR += DataBuffer.CharacterSkillBuffer[Cannoneer3.BARREL_ROULETTE].GetEffect(skillLevel).Info[CharacterSkillStat.damR]; } } else if (chr.IsJett) { /*if ((skillLevel = chr.GetSkillLevel(Jett2.PERSEVERANCE)) > 0) * { * var info = DataBuffer.CharacterSkillBuffer[Jett2.PERSEVERANCE].GetSkillEffect(skillLevel).Info; * int x = info[CharacterSkillStat.x]; * RecoveryHpR += x; * RecoveryMpR += x; * RecoveryTime = info[CharacterSkillStat.y] * 1000; * } */ } #endregion #endregion #region Buffs foreach (Buff buff in chr.GetBuffs()) { var buffInfo = buff.Effect.BuffInfo; foreach (var pair in buffInfo) { //if (pair.Key == MapleBuffStat.ENHANCED_MAXHP || pair.Key == MapleBuffStat.STACKING_MAXHP) //mhpX += pair.Value; if (pair.Key == MapleBuffStat.MAXHP_R || pair.Key == MapleBuffStat.STACKING_MAXHP_R) { mhpR += pair.Value; } //else if (pair.Key == MapleBuffStat.ENHANCED_MAXMP || pair.Key == MapleBuffStat.STACKING_MAXMP) //mmpX += pair.Value; else if (pair.Key == MapleBuffStat.MAXMP_R || pair.Key == MapleBuffStat.STACKING_MAXMP_R) { mmpR += pair.Value; } //else if (pair.Key == MapleBuffStat.WATK || pair.Key == MapleBuffStat.ENHANCED_WATK || pair.Key == MapleBuffStat.STACKING_WATK) //watk += pair.Value; //else if (pair.Key == MapleBuffStat.MATK || pair.Key == MapleBuffStat.ENHANCED_MATK || pair.Key == MapleBuffStat.STACKING_MATK) //matk += pair.Value; //else if (pair.Key == MapleBuffStat.CRIT || pair.Key == MapleBuffStat.STACKING_CRIT) //CritRate += pair.Value; else if (pair.Key == MapleBuffStat.STACKING_STATS) { Str += pair.Value; Dex += pair.Value; Int += pair.Value; Luk += pair.Value; } else if (pair.Key == MapleBuffStat.STACKING_STATS_R) { Str += (int)(chr.Str * (pair.Value / 100.0)); //todo: check if this isnt math.ceil Dex += (int)(chr.Dex * (pair.Value / 100.0)); Int += (int)(chr.Int * (pair.Value / 100.0)); Luk += (int)(chr.Luk * (pair.Value / 100.0)); } //else if (pair.Key == MapleBuffStat.HOLY_SYMBOL) { // ExpR += pair.Value; } } } #endregion #region Equips foreach (MapleItem item in chr.Inventory.GetItemsFromInventory(MapleInventoryType.Equipped)) { MapleEquip equip = item as MapleEquip; if (equip == null) { continue; } mhpX += equip.IncMhp; mmpX += equip.IncMmp; Str += equip.Str; Dex += equip.Dex; Int += equip.Int; Luk += equip.Luk; watk += equip.Pad; matk += equip.Mad; //todo: potential stuff from here } #endregion MaxHp = chr.MaxHp; MaxHp += lv2mhp * chr.Level; MaxHp += (int)((MaxHp) * (mhpR / 100.0)); MaxHp += mhpX; if (chr.Hp > MaxHp) { chr.AddHP(-(chr.Hp - MaxHp)); } MaxMp = chr.MaxMp; MaxMp += (int)(chr.MaxMp * (double)(mmpR / 100.0)); MaxMp += lv2mmp * chr.Level; MaxMp += mhpX; if (chr.Mp > MaxMp) { chr.AddMP(-(chr.Mp - MaxMp)); } Str += (short)(chr.Str * (double)(strR / 100.0)); Dex += (short)(chr.Dex * (double)(dexR / 100.0)); Int += (short)(chr.Int * (double)(intR / 100.0)); Luk += (short)(chr.Luk * (double)(lukR / 100.0)); bool mage = false; int primaryStat = 0; int secondaryStat = 0; MapleItem weapon = chr.Inventory.GetEquippedItem((short)MapleEquipPosition.Weapon); if (weapon == null) { MinDamage = 1; MaxDamage = 1; return; } MapleItemType weaponItemType = ItemConstants.GetMapleItemType(weapon.ItemId); switch ((chr.Job % 1000) / 100) { case 1: //Warrior-type primaryStat = Str; secondaryStat = Dex; break; case 2: //Magician-type case 7: //Luminous primaryStat = Int; secondaryStat = Luk; mage = true; break; case 3: //Archer-type primaryStat = Dex; secondaryStat = Str; break; case 4: //Thief-type primaryStat = Luk; secondaryStat = Dex; break; case 5: //Pirate-type if (weaponItemType == MapleItemType.Gun || weaponItemType == MapleItemType.SoulShooter) { primaryStat = Dex; secondaryStat = Str; } else //counts for cannons too { primaryStat = Str; secondaryStat = Dex; } break; case 6: //Xenon primaryStat = (Str + Dex + Luk); break; } if (!mage) { damR += pdR; //TODO: check, Not sure about this } CalculateDamageRange(weaponItemType, primaryStat, secondaryStat, mage ? matk : watk, damR, chr.IsFighter); }
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; }
public static void Handle(MapleClient c, PacketReader pr) { //6800 29939E7B 81BFD40F FD 00 60000000 00 00 037B 00 //6800 418AE151 6BE4D40F FF 00 01000000 00 00 47357C00 FE77AD00 00 00000000 00000000 00 00 00 //C101 CA566800 FD 60000000 00 60000000 //C101 68EB7A00 FF 01000000 00 F6761200 00 00000000 00000000 00 00 01000000 //effect //CD01 CA566800 [000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200] 0100 7B000300 00 00 00 00000000 00000000 00000000 00000000 00000000 0000 MapleCharacter chr = c.Account.Character; if (chr.Hidden) { return; } pr.Skip(4); //rnd num pr.Skip(4); //tickcount byte type = pr.ReadByte(); int damage = 0; pr.ReadByte(); damage = pr.ReadInt(); pr.Skip(2); int fake = 0; if (damage == -1) { fake = 4020002 + (chr.Job / 10 - 40) * 100000; if ((fake != NightLord.SHADOW_SHIFTER) && (fake != Shadower.SHADOW_SHIFTER)) { fake = NightLord.SHADOW_SHIFTER; } } switch (type) { case 0xFF: //mob damage { int mobid = pr.ReadInt(); int oid = pr.ReadInt(); MapleMonster mob = chr.Map.GetMob(oid); if (mob == null) { return; } byte direction = pr.ReadByte(); int skillid = pr.ReadInt(); int pDmg = pr.ReadInt(); byte defType = pr.ReadByte(); bool pPhysical = false; int pId = 0; byte pType = 0; Point pPos = Point.Empty; pr.ReadByte(); if (skillid != 0) { pPhysical = pr.ReadBool(); pId = pr.ReadInt(); pType = pr.ReadByte(); pr.Skip(4); pPos = pr.ReadPoint(); } byte offset = 0; int offsetD = 0; if (pr.Available == 1L) { offset = pr.ReadByte(); if ((offset == 1) && (pr.Available >= 4L)) { offsetD = pr.ReadInt(); } if ((offset < 0) || (offset > 2)) { offset = 0; } } BroadcastDamagePlayerPacket(chr, type, damage, mobid, direction, skillid, pDmg, pPhysical, pId, pType, pPos, offset, offsetD, fake); damage = DoMonsterDamageModifiers(damage, chr, mob, oid); if (damage > 0) { chr.AddHP(-damage); } } break; case 0xFD: //no mob, such as fall damage { short skill = pr.ReadShort(); //skill pr.ReadByte(); //? byte offset = 0; int offsetD = 0; if (pr.Available >= 1) { offset = pr.ReadByte(); if ((offset == 1) && (pr.Available >= 4)) { offsetD = pr.ReadInt(); } if ((sbyte)offset < 0 || offset > 2) { offset = 0; } } BroadcastDamagePlayerPacket(chr, type, damage, 0, 0, 0, 0, false, 0, 0, System.Drawing.Point.Empty, offset, offsetD, fake); if (damage > 0) { chr.AddHP(-damage); } } break; default: ServerConsole.Error("Invalid CharacterReceiveDamage type {0} ", type); break; } }
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 ApplyEffect(MapleCharacter source, MapleCharacter target) { int value; if (SkillConstants.IsHealSkill(Parent.SkillId) && Info.TryGetValue(CharacterSkillStat.hp, out value)) { int healHp = (int)((value / 100.0) * source.Stats.GetDamage()); target.AddHP(healHp); } #region Mist if (SkillConstants.IsMistSkill(Parent.SkillId)) { Point sourcePos = source.Position; BoundingBox boundingBox = CalculateBoundingBox(sourcePos, source.IsFacingLeft); source.Map.SpawnMist(Parent.SkillId, Level, source, boundingBox, sourcePos, Info[CharacterSkillStat.time] * 1000, false); } else if (Parent.SkillId == Priest.MYSTIC_DOOR) { MapleMap fromMap = source.Map; if (fromMap.MysticDoorLimit) { return; } source.CancelDoor(Priest.MYSTIC_DOOR); int partyId = source.Party?.Id ?? -1; Point fromMapPosition = source.Map.GetDropPositionBelow(source.Position, source.Position); int time = Info[CharacterSkillStat.time] * 1000; MapleMap toMap = Program.GetChannelServer(source.Client.Channel).GetMap(source.Map.ReturnMap); if (toMap != null) { WzMap.Portal toPortal = toMap.TownPortal; if (toPortal != null) { Point toMapPosition = toMap.GetDropPositionBelow(toPortal.Position, toPortal.Position); MysticDoor sourceDoor = new MysticDoor(Parent.SkillId, source, fromMapPosition, fromMap, toMap, toPortal, time, true); fromMap.SpawnStaticObject(sourceDoor); source.AddDoor(sourceDoor); } } } #endregion #region Summons if (Parent.HasSummon) { source.RemoveSummon(Parent.SkillId); //Remove old one if exists WzCharacterSkill.SummonAttackInfo info = Parent.SummonInfo; MapleSummon summon = new MapleSummon(source.Map.GetNewObjectId(), Parent.SkillId, source.Position, info.Type, info.MovementType, source, Level, (uint)Info[CharacterSkillStat.time] * 1000); source.AddSummon(summon); } #endregion //Custom handling: switch (Parent.SkillId) { case Hunter.QUIVER_CARTRIDGE: QuiverCartridgeSystem qcs = source.Resource as QuiverCartridgeSystem; if (qcs != null) { qcs.SwitchCurrentArrow(source.Client); } break; case Priest.HOLY_MAGIC_SHELL: case SuperGameMaster.HEAL_DISPEL: target.AddHP(target.Stats.MaxHp); break; case Bishop.RESURRECTION: case SuperGameMaster.RESURRECTION: if (target.IsDead) { target.Revive(false, false, true); } break; } }
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); }