public static void DecryptSkill(Player player, ref MsgInteract packet, out Skill skill) { byte[] buffer = packet; var id = Convert.ToUInt16(((long)buffer[24] & 0xFF) | (((long)buffer[25] & 0xFF) << 8)); id ^= 0x915d; id ^= (ushort)player.UniqueId; id = (ushort)(id << 0x3 | id >> 0xd); id -= 0xeb42; long x = (buffer[16] & 0xFF) | ((buffer[17] & 0xFF) << 8); long y = (buffer[18] & 0xFF) | ((buffer[19] & 0xFF) << 8); x = x ^ (player.UniqueId & 0xffff) ^ 0x2ed6; x = ((x << 1) | ((x & 0x8000) >> 15)) & 0xffff; x |= 0xffff0000; x -= 0xffff22ee; y = y ^ (player.UniqueId & 0xffff) ^ 0xb99b; y = ((y << 5) | ((y & 0xF800) >> 11)) & 0xffff; y |= 0xffff0000; y -= 0xffff8922; var target = BitConverter.ToInt32(buffer, 12); target = (int)((((target & 0xffffe000) >> 13) | ((target & 0x1fff) << 19)) ^ 0x5F2D2463 ^ player.UniqueId) - 0x746F4AE6; packet.TargetUniqueId = target; packet.X = (ushort)x; packet.Y = (ushort)y; skill = player.Skills[(SkillId)id]; BufferPool.RecycleBuffer(buffer); }
public override void Attack() { Owner.CurrentSkill = new Skill((ushort)Owner.MagicType, 0, 0); //Thunder ScreenSystem.Send(Owner, MsgInteract.Create(Owner, Owner.CurrentTarget, MsgInteractType.Magic, 133337)); ScreenSystem.Send(Owner, MsgMagicEffect.Create(Owner, Owner.CurrentTarget, 133337)); Owner.LastAttack = DateTime.UtcNow; Owner.CurrentTarget.GetHit(Owner, 133337); }
public virtual void KilledFrom(YiObject attacker) { if (HasFlag(StatusEffect.SuperMan) || HasFlag(StatusEffect.Cyclone)) { (attacker as Player)?.Send(MsgInteract.Create(attacker, this, MsgInteractType.Death, 0xFFFF * attacker.XpKills)); } else { ScreenSystem.Send(this, MsgInteract.Die(attacker, this), true); } var human = attacker; if (human != null) { human.PkPoints++; } }
public static int PhysicalAttack(YiObj attacker, MsgInteractType attackType = MsgInteractType.Physical) { if (!CanAttackPhysical(attacker, attacker.CurrentTarget)) { return(-1); } if (attacker.HasFlag(StatusEffect.Invisibility)) { attacker.RemoveStatusEffect(StatusEffect.Invisibility); } if (attacker is Player player) { if (player.AttackJob != null) { player.AttackJob.Cancelled = true; } if (player.CurrentTarget != null && player.CurrentTarget.Alive) { player.AttackJob = YiScheduler.Instance.DoReturn(TimeSpan.FromMilliseconds(attacker.AttackSpeed), () => MsgInteract.Handle(player, MsgInteract.Create(attacker, attacker.CurrentTarget, attackType, 0))); } } return(AttackCalcs.GetDamage(attacker, attacker.CurrentTarget, attackType)); }
public static void HandleInteract(Character pRole, MsgInteract pMsg) { if (pRole == null || pRole.BattleSystem == null) { return; } pRole.BattleSystem.DestroyAutoAttack(); pRole.BattleSystem.ResetBattle(); if (pRole.BattleSystem.QueryMagic() != null) { pRole.BattleSystem.QueryMagic().SetMagicState(0); pRole.BattleSystem.QueryMagic().BreakAutoAttack(); pRole.BattleSystem.QueryMagic().AbortMagic(true); } if (!pRole.IsAlive) { return; } var obj = pRole.BattleSystem.FindRole(pMsg.TargetIdentity); if (obj == null && pMsg.Action != InteractionType.ACT_ITR_MAGIC_ATTACK && pMsg.Action != InteractionType.ACT_ITR_COUNTER_KILL_SWITCH && pMsg.Action != InteractionType.ACT_ITR_PRESENT_EMONEY) { return; } switch (pMsg.Action) { #region 2/28 - Meele and Bow case InteractionType.ACT_ITR_SHOOT: case InteractionType.ACT_ITR_ATTACK: { pRole.BattleSystem.CreateBattle(pMsg.TargetIdentity); pRole.BattleSystem.SetAutoAttack(); pRole.SetAttackTarget(obj); break; } #endregion #region 8 - Court case InteractionType.ACT_ITR_COURT: { if (pRole.Identity == pMsg.TargetIdentity) { return; } Character pTarget; if (pRole.Map.Players.TryGetValue(pMsg.TargetIdentity, out pTarget)) { if (pTarget.Mate != ServerString.NOMATE_NAME) { pRole.Send(ServerString.TARGET_ALREADY_MARRIED); return; } if (pRole.Mate != ServerString.NOMATE_NAME) { pRole.Send(ServerString.YOURE_ALREADY_MARRIED); return; } if (pTarget.Gender == pRole.Gender) { pRole.Send(ServerString.NOT_ALLOWED_SAME_GENDER_MARRIAGE); return; } pTarget.SetMarryRequest(pRole.Identity); pTarget.Send(pMsg); } else { pRole.Send(ServerString.MARRIAGE_NOT_APPLY); return; } break; } #endregion #region 9 - Marry case InteractionType.ACT_ITR_MARRY: { if (pRole.Identity == pMsg.TargetIdentity) { return; } Character pTarget; if (pRole.Map.Players.TryGetValue(pMsg.TargetIdentity, out pTarget)) { if (pTarget.Mate != ServerString.NOMATE_NAME) { pRole.Send(ServerString.TARGET_ALREADY_MARRIED); return; } if (pRole.Mate != ServerString.NOMATE_NAME) { pRole.Send(ServerString.YOURE_ALREADY_MARRIED); return; } if (pTarget.Gender == pRole.Gender) { pRole.Send(ServerString.NOT_ALLOWED_SAME_GENDER_MARRIAGE); return; } if (!pRole.FetchMarryRequest(pTarget.Identity)) { pRole.Send(ServerString.MARRIAGE_NOT_APPLY); return; } pRole.Mate = pTarget.Name; pTarget.Mate = pRole.Name; MsgName msg = new MsgName { Identity = pRole.Identity, Action = StringAction.MATE }; msg.Append(pRole.Mate); pRole.Send(msg); msg = new MsgName { Identity = pTarget.Identity, Action = StringAction.MATE }; msg.Append(pTarget.Mate); pTarget.Send(msg); if (pRole.Family != null && pTarget.Family == null) { pRole.Family.AppendMember(pRole, pTarget); } else if (pRole.Family == null && pTarget.Family != null) { pTarget.Family.AppendMember(pTarget, pRole); } ServerKernel.SendMessageToAll(string.Format(ServerString.STR_MARRY, pRole.Name, pTarget.Name), ChatTone.CENTER); } else { pRole.Send(ServerString.MARRIAGE_NOT_APPLY); return; } break; } #endregion #region 24 - Magic Attack case InteractionType.ACT_ITR_MAGIC_ATTACK: { #region TemporaryDecryption ushort skillId = Convert.ToUInt16(((long)pMsg[24] & 0xFF) | (((long)pMsg[25] & 0xFF) << 8)); skillId ^= 0x915d; skillId ^= (ushort)pRole.Identity; skillId = (ushort)(skillId << 0x3 | skillId >> 0xd); skillId -= 0xeb42; uint Target = ((uint)pMsg[12] & 0xFF) | (((uint)pMsg[13] & 0xFF) << 8) | (((uint)pMsg[14] & 0xFF) << 16) | (((uint)pMsg[15] & 0xFF) << 24); Target = ((((Target & 0xffffe000) >> 13) | ((Target & 0x1fff) << 19)) ^ 0x5F2D2463 ^ pRole.Identity) - 0x746F4AE6; pMsg.TargetIdentity = Target; ushort TargetX = 0; ushort TargetY = 0; long xx = (pMsg[16] & 0xFF) | ((pMsg[17] & 0xFF) << 8); long yy = (pMsg[18] & 0xFF) | ((pMsg[19] & 0xFF) << 8); xx = xx ^ (pRole.Identity & 0xffff) ^ 0x2ed6; xx = ((xx << 1) | ((xx & 0x8000) >> 15)) & 0xffff; xx |= 0xffff0000; xx -= 0xffff22ee; yy = yy ^ (pRole.Identity & 0xffff) ^ 0xb99b; yy = ((yy << 5) | ((yy & 0xF800) >> 11)) & 0xffff; yy |= 0xffff0000; yy -= 0xffff8922; TargetX = Convert.ToUInt16(xx); TargetY = Convert.ToUInt16(yy); pMsg.MagicType = skillId; pMsg.CellX = TargetX; pMsg.CellY = TargetY; #endregion if (pRole.IsAlive) { pRole.ProcessMagicAttack(pMsg.MagicType, pMsg.TargetIdentity, pMsg.CellX, pMsg.CellY); } break; } #endregion #region 39 - Claim CPs case InteractionType.ACT_ITR_PRESENT_EMONEY: if (pRole.CoinMoney > 0) { pRole.AwardEmoney(pRole.CoinMoney, true); pMsg.Amount = pRole.CoinMoney; pRole.CoinMoney = 0; pRole.Send(pMsg); } break; #endregion #region 44 - Counter Kill Switch case InteractionType.ACT_ITR_COUNTER_KILL_SWITCH: { if (pRole.Profession / 10 != 5 || !pRole.IsPureClass()) { pRole.Send(ServerString.STR_SCAPEGOAT_ONLY_PURE_NINJA); return; } if (!pRole.IsAlive || pRole.IsWing()) { return; } if (pRole.Scapegoat) // disable { pMsg.TargetIdentity = pMsg.EntityIdentity = pRole.Identity; pMsg.Damage = 0; pMsg.CellX = pRole.MapX; pMsg.CellY = pRole.MapY; pRole.Send(pMsg); pRole.Scapegoat = false; } else { pMsg.TargetIdentity = pMsg.EntityIdentity = pRole.Identity; pMsg.Damage = 1; pMsg.CellX = pRole.MapX; pMsg.CellY = pRole.MapY; pRole.Send(pMsg); pRole.Scapegoat = true; } break; } #endregion #region 36 - QuestJar case InteractionType.ACT_ITR_INCREASE_JAR: { // TODO Only temporal for now. But allowed login/logout the player. QuestJar quest = ServerKernel.PlayerQuests.Where(x => x.Player.Identity == pRole.Identity).FirstOrDefault(); if (quest != null) { pMsg.Amount = quest.Kills; } pRole.Send(pMsg); break; } #endregion default: ServerKernel.Log.SaveLog("Missing Interaction Type: " + pMsg.Action, true, "itr_msg", LogType.WARNING); break; } }
public static void UseMagic(AdvancedEntity aAttacker, AdvancedEntity aTarget, UInt16 aTargetX, UInt16 aTargetY) { try { // a lot of logic depends on the fact that the attacker is a player... Player attacker = aAttacker as Player; if (!aAttacker.IsAlive()) { return; } if (aAttacker.IsPlayer()) { if (attacker.MagicType == 8000 || attacker.MagicType == 8001) { Item arrow = attacker.GetItemByPos(5); if (arrow.Type / 10000 != 105) { return; } if (attacker.MagicType == 8000) { if (arrow.CurDura < 5) { return; } } if (attacker.MagicType == 8001) { if (arrow.CurDura < 3) { return; } } } } Magic.Info Info = new Magic.Info(); if (!Database.AllMagics.TryGetValue((aAttacker.MagicType * 10) + aAttacker.MagicLevel, out Info)) { return; } GameMap Map = aAttacker.Map; if (aAttacker.IsPlayer() && Program.Debug) { attacker.SendSysMsg(String.Format("Using magic skill {0} [sort={1}, power={2}, status={3}]", Info.Type, Info.Sort, Info.Power, Info.Status)); } #region Fly | IsWing_Disable if (Info.Type == 8002 || Info.Type == 8003) { if (Map.IsWing_Disable()) { return; } } #endregion #region Use Mp/PP/Xp if (aAttacker.IsPlayer()) { if (Info.UseMP != 0 && attacker.CurMP < Info.UseMP) { return; } if (Info.UseEP != 0 && attacker.Energy < Info.UseEP) { return; } if (Info.UseXP == Magic.TYPE_XPSKILL && attacker.XP < 100) { return; } if (Info.UseMP != 0 && attacker.Map.Id != 1039) { attacker.CurMP -= (UInt16)Info.UseMP; attacker.Send(new MsgUserAttrib(attacker, attacker.CurMP, MsgUserAttrib.AttributeType.Mana)); } if (Info.UseEP != 0 && attacker.Map.Id != 1039) { attacker.Energy -= (Byte)Info.UseEP; attacker.Send(new MsgUserAttrib(attacker, attacker.Energy, MsgUserAttrib.AttributeType.Energy)); } if (Info.UseXP == Magic.TYPE_XPSKILL) { attacker.XP = 0; attacker.Send(new MsgUserAttrib(attacker, attacker.XP, MsgUserAttrib.AttributeType.XP)); attacker.DetachStatus(Status.XpFull); } } #endregion #region Intone if (Info.IntoneDuration > 0) { aAttacker.MagicIntone = true; // TODO implement intonation //Thread.Sleep((Int32)Info.IntoneDuration); if (!aAttacker.MagicIntone) { return; } aAttacker.MagicIntone = false; } #endregion #region Potential targets AdvancedEntity[] potential_targets = new AdvancedEntity[0]; if (aTarget == null || Info.Sort == MagicSort.RecoverSingleHP || Info.Sort == MagicSort.AttackRoundHP || Info.Sort == MagicSort.DispatchXP) { switch (Info.Sort) { case MagicSort.RecoverSingleHP: { // team healing... if (Info.Type == 1055 || Info.Type == 1170) { if ((aTarget.IsPlayer() && (aTarget as Player).Team == null)) { potential_targets = new AdvancedEntity[] { aTarget }; break; } if (aAttacker.IsPlayer()) // only a player can have a team... { potential_targets = Battle.GetTargetsForType11(attacker); } } else { potential_targets = new AdvancedEntity[] { aTarget } }; break; } case MagicSort.AttackSectorHP: potential_targets = Battle.GetTargetsForType04(aAttacker, aTargetX, aTargetY, Info.Distance, Info.Range); break; case MagicSort.AttackRoundHP: { if (aTarget != null) { aTargetX = aTarget.X; aTargetY = aTarget.Y; aTarget = null; } potential_targets = Battle.GetTargetsForType05(aAttacker, aTargetX, aTargetY, Info.Range); break; } case MagicSort.DispatchXP: { if (aAttacker.IsPlayer()) // only a player can have a team... { potential_targets = Battle.GetTargetsForType11(attacker); } break; } case MagicSort.Line: { potential_targets = Battle.GetTargetsForType14(aAttacker, aTargetX, aTargetY, Info.Range); break; } } } else { potential_targets = new AdvancedEntity[] { aTarget } }; #endregion Dictionary <AdvancedEntity, Int32> targets = new Dictionary <AdvancedEntity, Int32>(potential_targets.Length); UInt32 Exp = 0; UInt32 MagicExp = 0; foreach (AdvancedEntity entity in potential_targets) { Boolean Reflected = false; Player Player = entity as Player; Monster Monster = entity as Monster; TerrainNPC Npc = entity as TerrainNPC; // entity == NULL || entity isn't alive and not using pray if (entity == null || (!entity.IsAlive() && Info.Sort != MagicSort.RecoverSingleStatus)) { continue; } if (aAttacker.Map != entity.Map) { continue; } if (!MyMath.CanSee(aAttacker.X, aAttacker.Y, entity.X, entity.Y, (Int32)Info.Distance)) { continue; } if (Info.Target == 0 && aAttacker.UniqId == entity.UniqId) { continue; } else if (Info.Target == 2 && aAttacker.UniqId != entity.UniqId) { continue; } else if (Info.Target == 4 && aAttacker.UniqId == entity.UniqId) { continue; } else if (Info.Target == 8 && aAttacker.UniqId == entity.UniqId && !((Info.Type - (Info.Type % 1000)) == 10000)) { continue; } if (Info.Ground && entity.IsPlayer()) // Ground skill { if (Player.IsFlying()) { continue; } } #region Blue name (Crime) if (aAttacker.IsPlayer() && Info.Crime) // Is a crime to use the skill { if (entity.IsPlayer()) { if (!CanAttack(attacker, Player)) { continue; } if (!Map.IsPkField() && !Map.IsSynMap() && !Map.IsPrisonMap()) { if (!Player.IsCriminal()) { attacker.AttachStatus(Status.Crime, 25000); } } } else if (entity.IsMonster()) { if (!CanAttack(attacker, Monster)) { continue; } if ((Byte)(Monster.Id / 100) == 9) //Is a guard { attacker.AttachStatus(Status.Crime, 25000); } } } #endregion #region Get base damage Int32 damage = 0; if (Info.Sort == MagicSort.RecoverSingleHP || Info.Sort == MagicSort.AttackSingleStatus || Info.Sort == MagicSort.DispatchXP || Info.Sort == MagicSort.Transform || Info.Sort == MagicSort.AddMana) { damage = (Int32)Info.Power; } else if (Info.Sort == MagicSort.RecoverSingleStatus) { damage = entity.MaxHP; } else if (Info.Sort == MagicSort.DecLife) { damage = (Int32)(entity.CurHP * ((Double)(Info.Power - 30000) / 100.00)); } else { if (aAttacker.IsPlayer()) { if (entity.IsPlayer()) { damage = MyMath.GetDamagePlayer2Player(attacker, Player, attacker.MagicType, attacker.MagicLevel); } else if (entity.IsMonster()) { damage = MyMath.GetDamagePlayer2Monster(attacker, Monster, attacker.MagicType, attacker.MagicLevel); } else if (entity.IsTerrainNPC()) { damage = MyMath.GetDamagePlayer2Environment(attacker, Npc, attacker.MagicType, attacker.MagicLevel); } } else { if (entity.IsPlayer()) { damage = MyMath.GetDamageMonster2Player((Monster)aAttacker, Player, aAttacker.MagicType, aAttacker.MagicLevel); } } } //TargetType -> 8; Passive skill if (Info.Target != 8 && Info.Success != 100 && !MyMath.Success(Info.Success)) { damage = 0; } #endregion #region Process damage / skill switch (Info.Sort) { case MagicSort.RecoverSingleHP: { if (entity.CurHP + damage >= entity.MaxHP) { MagicExp += (UInt32)(entity.MaxHP - entity.CurHP); entity.CurHP = entity.MaxHP; } else { MagicExp += (UInt32)damage; entity.CurHP += damage; } if (entity.IsPlayer()) { var msg = new MsgUserAttrib(Player, Player.CurHP, MsgUserAttrib.AttributeType.Life); Player.Send(msg); if (Player.Team != null) { Player.Team.BroadcastMsg(msg); } msg = null; } break; } case MagicSort.AttackSingleStatus: { int duration = (int)Info.StepSecs * 1000; double power = ((double)(damage - 30000) / 100.00); switch (aAttacker.MagicType) { case 1015: { entity.AttachStatus(Status.Accuracy, duration, power); if (entity.IsPlayer()) { MyMath.GetEquipStats(Player); } break; } case 1020: { entity.AttachStatus(Status.MagicDefense, duration, power); if (entity.IsPlayer()) { MyMath.GetEquipStats(Player); } break; } case 1025: { if (entity.HasStatus(Status.SuperSpeed)) { entity.DetachStatus(Status.SuperSpeed); } entity.AttachStatus(Status.SuperAtk, duration, power); if (entity.IsPlayer()) { MyMath.GetEquipStats(Player); } break; } case 1075: { ++MagicExp; entity.AttachStatus(Status.Hidden, duration); break; } case 1085: { ++MagicExp; entity.AttachStatus(Status.Accuracy, duration, power); if (entity.IsPlayer()) { MyMath.GetEquipStats(Player); } break; } case 1090: { ++MagicExp; entity.AttachStatus(Status.MagicDefense, duration, power); if (entity.IsPlayer()) { MyMath.GetEquipStats(Player); } break; } case 1095: { ++MagicExp; entity.AttachStatus(Status.MagicAttack, duration, power); if (entity.IsPlayer()) { MyMath.GetEquipStats(Player); } break; } case 1110: { if (entity.HasStatus(Status.SuperAtk)) { entity.DetachStatus(Status.SuperAtk); } entity.AttachStatus(Status.SuperSpeed, duration, power); if (entity.IsPlayer()) { MyMath.GetEquipStats(Player); } break; } case 8002: { if (entity.HasStatus(Status.MagicDefense)) { break; } entity.AttachStatus(Status.Flying, duration); break; } case 8003: { if (entity.HasStatus(Status.MagicDefense)) { break; } entity.AttachStatus(Status.Flying, duration); break; } case 9000: { ++MagicExp; entity.AttachStatus((Status)Info.Status, -1, power); break; } case 9876: { entity.AttachStatus(Status.CastingPray); if (entity.IsPlayer()) { Player.CastingPray = true; Player.PrayMap = entity.Map.Id; Player.PrayX = entity.X; Player.PrayY = entity.Y; } break; } case 10203: { StatusEffect effect; if (entity.GetStatus(Status.MagicDefense, out effect)) { effect.Data = power; effect.ResetTimeout(duration); break; } entity.AttachStatus(Status.MagicDefense, duration, power); if (entity.IsPlayer()) { MyMath.GetEquipStats(Player); } break; } default: sLogger.Warn("Magic {0} is not implemented !", aAttacker.MagicType); break; } damage = 0; break; } case MagicSort.RecoverSingleStatus: { if (entity.IsPlayer() && !entity.IsAlive()) { Player.Reborn(false); } break; } case MagicSort.DispatchXP: { if (entity.IsPlayer()) { if (Player.XP + damage >= 100) { Player.XP = 100; } else { Player.XP += (Byte)damage; } Player.Send(new MsgUserAttrib(Player, Player.XP, MsgUserAttrib.AttributeType.XP)); } break; } case MagicSort.Transform: { if (entity.IsPlayer()) { MonsterInfo MonsterInfo; if (Database.AllMonsters.TryGetValue(damage, out MonsterInfo)) { MagicExp++; Player.TransformEndTime = Environment.TickCount + ((Int32)Info.StepSecs * 1000); // TODO re-enable transformation skills //Player.AddTransform(MonsterInfo.Look); Player.MinAtk = (Int32)MonsterInfo.MinAtk; Player.MaxAtk = (Int32)MonsterInfo.MaxAtk; Player.Defence = (Int32)MonsterInfo.Defense; Player.MagicAtk = 0; Player.MagicDef = (Int32)MonsterInfo.MagicDef; Player.MagicBlock = 0; Player.Dodge = MonsterInfo.Dodge; Player.Dexterity = 1000; Player.AtkRange = MonsterInfo.AtkRange; Player.AtkSpeed = MonsterInfo.AtkSpeed; Player.AtkType = 2; Player.Bless = 1.00; Player.GemBonus = 1.00; if (Player.CurHP >= Player.MaxHP) { Player.CurHP = Player.MaxHP; } Player.CurHP = (Int32)((Double)MonsterInfo.Life * ((Double)Player.CurHP / (Double)Player.MaxHP)); Player.MaxHP = MonsterInfo.Life; Player.Send(new MsgUserAttrib(Player, Player.CurHP, MsgUserAttrib.AttributeType.Life)); Player.Send(new MsgUserAttrib(Player, Player.MaxHP, (MsgUserAttrib.AttributeType.Life + 1))); if (Player.Team != null) { Player.Team.BroadcastMsg(new MsgUserAttrib(Player, Player.CurHP, MsgUserAttrib.AttributeType.Life)); Player.Team.BroadcastMsg(new MsgUserAttrib(Player, Player.MaxHP, (MsgUserAttrib.AttributeType.Life + 1))); } World.BroadcastRoomMsg(Player, new MsgUserAttrib(Player, Player.Look, MsgUserAttrib.AttributeType.Look), true); } } damage = 0; break; } case MagicSort.AddMana: { if (entity.IsPlayer()) { if (Player.CurMP + damage >= Player.MaxMP) { MagicExp += (UInt32)(Player.MaxMP - Player.CurMP); Player.CurMP = Player.MaxMP; } else { MagicExp += (UInt32)damage; Player.CurMP += (UInt16)damage; } Player.Send(new MsgUserAttrib(Player, Player.CurMP, MsgUserAttrib.AttributeType.Mana)); } break; } case MagicSort.CallPet: { if (!aAttacker.IsPlayer()) { sLogger.Error("MagicSort::CallPet used by a non-player entity."); return; } damage = 0; MagicExp += 1; Generator.generatePet((Player)aAttacker, (Int32)Info.Power); break; } default: { if (entity.IsPlayer()) { Player.RemoveDefDura(); } #region Not a player || Not reflected if (!entity.IsPlayer() || (entity.IsPlayer() && !Player.Reflect())) { if (damage >= entity.CurHP) { if (entity.IsPlayer()) { Player.Die(aAttacker); } else if (entity.IsMonster()) { if (aAttacker.IsPlayer()) { if (attacker.XP < 99) { ++attacker.XP; } StatusEffect effect; if (attacker.GetStatus(Status.SuperSpeed, out effect)) { effect.IncreaseDuration(820); ++attacker.CurKO; } if (attacker.GetStatus(Status.SuperAtk, out effect)) { effect.IncreaseDuration(820); ++attacker.CurKO; } Int32 CurHP = entity.CurHP; Monster.Die(attacker.UniqId); Exp += AdjustExp(CurHP, attacker, Monster); MagicExp += AdjustExp(CurHP, attacker, Monster); Int32 Bonus = (Int32)(Monster.MaxHP * 0.05); if (attacker.Team != null) { attacker.Team.AwardMemberExp(attacker, Monster, Bonus); } UInt32 BonusExp = AdjustExp(Bonus, attacker, Monster); attacker.AddExp(BonusExp, true); attacker.SendSysMsg(String.Format(StrRes.STR_KILL_EXPERIENCE, BonusExp)); } } else if (entity.IsTerrainNPC()) { if (attacker.IsPlayer()) { if (attacker.XP < 99) { attacker.XP++; } Int32 CurHP = entity.CurHP; if (Npc.Type == 21 || Npc.Type == 22) { Exp += AdjustExp(CurHP, attacker, Npc); MagicExp += AdjustExp(CurHP, attacker, Npc); Int32 Bonus = (Int32)(entity.MaxHP * 0.05); UInt32 BonusExp = AdjustExp(Bonus, attacker, Npc); attacker.AddExp(BonusExp, true); } else if (Npc.Type == (Byte)TerrainNPC.NpcType.SynFlag) { if (attacker.Syndicate != null) { // TODO re-enable donation gain on pole //if (attacker.Map.InWar) // if (attacker.Syndicate.Id != attacker.Map.Holder) // { // attacker.Money += (UInt32)(CurHP / 10000); // attacker.Send(new MsgUserAttrib(attacker, attacker.Money, MsgUserAttrib.AttributeType.Money)); // Syndicate.Member Member = attacker.Syndicate.GetMemberInfo(attacker.UniqId); // if (Member != null) // { // Member.Donation += (UInt32)(CurHP / 10000); // attacker.Syndicate.Money += (UInt32)(CurHP / 10000); // } // } } } Npc.GetAttacked(attacker, Npc.CurHP); World.BroadcastMapMsg(attacker, new MsgInteract(attacker, entity, 1, MsgInteract.Action.Kill), true); Npc.Die(); } } if (!entity.IsTerrainNPC()) { if (aAttacker.IsPlayer()) { if (!entity.IsMonster() || (!aAttacker.HasStatus(Status.SuperAtk) && !aAttacker.HasStatus(Status.SuperSpeed))) { World.BroadcastMapMsg(attacker, new MsgInteract(aAttacker, entity, 1, MsgInteract.Action.Kill), true); } else { World.BroadcastMapMsg(attacker, new MsgInteract(aAttacker, entity, 0xFFFF * (attacker.CurKO + 1), MsgInteract.Action.Kill), true); } } else { World.BroadcastMapMsg(aAttacker, new MsgInteract(aAttacker, entity, 1, MsgInteract.Action.Kill)); } } } else { entity.CurHP -= damage; if (entity.IsPlayer()) { Player.Send(new MsgUserAttrib(entity, entity.CurHP, MsgUserAttrib.AttributeType.Life)); if (Player.Team != null) { Player.Team.BroadcastMsg(new MsgUserAttrib(entity, entity.CurHP, MsgUserAttrib.AttributeType.Life)); } if (Player.Action == Emotion.SitDown) { Player.Energy /= 2; Player.Send(new MsgUserAttrib(Player, Player.Energy, MsgUserAttrib.AttributeType.Energy)); Player.Action = Emotion.StandBy; World.BroadcastRoomMsg(Player, new MsgAction(Player, (int)Player.Action, MsgAction.Action.Emotion), true); } } else if (entity.IsMonster()) { if (aAttacker.IsPlayer()) { Exp += AdjustExp(damage, attacker, Monster); MagicExp += (UInt32)AdjustExp(damage, attacker, Monster); } } else if (entity.IsTerrainNPC()) { if (aAttacker.IsPlayer()) { if (Npc.Type == 21 || Npc.Type == 22) { Exp += AdjustExp(damage, attacker, Npc); MagicExp += (UInt32)AdjustExp(damage, attacker, Npc); } else if (Npc.Type == (Byte)TerrainNPC.NpcType.SynFlag) { if (attacker.Syndicate != null) { // TODO re-enable donation gain on pole //if (attacker.Map.InWar) // if (attacker.Syndicate.Id != attacker.Map.Holder) // { // attacker.Money += (UInt32)(damage / 10000); // attacker.Send(new MsgUserAttrib(attacker, attacker.Money, MsgUserAttrib.AttributeType.Money)); // Syndicate.Member Member = attacker.Syndicate.GetMemberInfo(attacker.UniqId); // if (Member != null) // { // Member.Donation += (UInt32)(damage / 10000); // attacker.Syndicate.Money += (UInt32)(damage / 10000); // attacker.Send(new MsgSynAttrInfo(attacker.UniqId, attacker.Syndicate)); // } // } } } Npc.GetAttacked(attacker, damage); } } } } #endregion #region Reflected else { if (damage > 2000) { damage = 2000; } var msg = new MsgInteract(entity, aAttacker, damage, MsgInteract.Action.ReflectMagic); if (aAttacker.IsPlayer()) { World.BroadcastMapMsg(attacker, msg, true); } else { World.BroadcastMapMsg(aAttacker, msg); } if (damage >= aAttacker.CurHP) { if (aAttacker.IsPlayer()) { attacker.Die(null); } else { ((Monster)aAttacker).Die(entity.UniqId); } World.BroadcastMapMsg(Player, new MsgInteract(entity, aAttacker, 1, MsgInteract.Action.Kill), true); } else { aAttacker.CurHP -= damage; var msg2 = new MsgUserAttrib(aAttacker, aAttacker.CurHP, MsgUserAttrib.AttributeType.Life); if (aAttacker.IsPlayer()) { attacker.Send(msg2); if (attacker.Team != null) { attacker.Team.BroadcastMsg(msg2); } } else { World.BroadcastMapMsg(aAttacker, msg2); } } Reflected = true; } #endregion break; } } #endregion if (aTarget != null && Info.Sort != MagicSort.DispatchXP && Info.Sort != MagicSort.RecoverSingleHP && !Reflected) { var msg = new MsgMagicEffect(aAttacker, aTarget, damage, aTargetX, aTargetY); if (aAttacker.IsPlayer()) { World.BroadcastMapMsg(attacker, msg, true); } else { World.BroadcastMapMsg(aAttacker, msg); } } else if (!Reflected) { targets.Add(entity, damage); } } #region Player: Update LastAttackTick if (aAttacker.IsPlayer()) { attacker.LastAttackTick = Environment.TickCount; } #endregion #region Player: Remove Dura if (aAttacker.IsPlayer() && aAttacker.Map.Id != 1039) { if (attacker.MagicType == 8000) { for (SByte i = 0; i < 5; i++) { attacker.RemoveAtkDura(); } } else if (attacker.MagicType == 8001) { for (SByte i = 0; i < 3; i++) { attacker.RemoveAtkDura(); } } else { attacker.RemoveAtkDura(); } } #endregion #region Player: Add Exp if (aAttacker.IsPlayer()) { attacker.AddExp(Exp, true); if (MagicExp > 0 && Info.Sort != MagicSort.AtkStatus) { attacker.AddMagicExp(attacker.MagicType, MagicExp); } else if (MagicExp > 0) { attacker.AddMagicExp(attacker.MagicType, 1); } } #endregion if (aTarget == null || Info.Sort == MagicSort.DispatchXP || Info.Sort == MagicSort.RecoverSingleHP) { var msg = new MsgMagicEffect(aAttacker, targets, aTargetX, aTargetY); if (aAttacker.IsPlayer()) { World.BroadcastMapMsg(attacker, msg, true); } else { World.BroadcastMapMsg(aAttacker, msg); } } #region Player: Activate the weapon attribute (e.g. Poison Blade) if (aAttacker.IsPlayer() && aAttacker.Map.Id != 1039) { Battle.WeaponAttribute(attacker, null); } #endregion } catch (Exception exc) { sLogger.Error(exc); } }