// ReSharper disable once UnusedParameter.Local private void SpawnCircle(int round) { if (_map != null) { MapCell cell = _map.Map.GetRandomPosition(); int circleId = _map.GetNextMonsterId(); MapMonster circle = new MapMonster { MonsterVNum = 2018, MapX = cell.X, MapY = cell.Y, MapMonsterId = circleId, IsHostile = false, IsMoving = false, ShouldRespawn = false }; circle.Initialize(_map); circle.NoAggresiveIcon = true; _map.AddMonster(circle); _map.Broadcast(circle.GenerateIn()); _map.Broadcast(StaticPacketHelper.GenerateEff(UserType.Monster, circleId, 4660)); Observable.Timer(TimeSpan.FromSeconds(3)).Subscribe(observer => { if (_map != null) { _map.Broadcast(StaticPacketHelper.SkillUsed(UserType.Monster, circleId, 3, circleId, 1220, 220, 0, 4983, cell.X, cell.Y, true, 0, 65535, 0, 0)); foreach (Character character in _map.GetCharactersInRange(cell.X, cell.Y, 2)) { if (!_map.Sessions.Skip(3).Any()) { // Your reward for the last three living players } character.IsCustomSpeed = false; character.RemoveVehicle(); character.GetDamage(655350); Observable.Timer(TimeSpan.FromMilliseconds(1000)).Subscribe(o => ServerManager.Instance.AskRevive(character.CharacterId)); } _map.RemoveMonster(circle); _map.Broadcast(StaticPacketHelper.Out(UserType.Monster, circle.MapMonsterId)); } }); } }
private void targetHit2(ClientSession targetSession, NpcMonsterSkill npcMonsterSkill, int damage, int hitmode) { if (targetSession.Character.Hp > 0) { targetSession.Character.GetDamage(damage); MapInstance.Broadcast(null, ServerManager.Instance.GetUserMethod <string>(Target, "GenerateStat"), ReceiverType.OnlySomeone, string.Empty, Target); MapInstance.Broadcast(npcMonsterSkill != null ? StaticPacketHelper.SkillUsed(UserType.Monster, MapMonsterId, 1, Target, npcMonsterSkill.SkillVNum, npcMonsterSkill.Skill.Cooldown, npcMonsterSkill.Skill.AttackAnimation, npcMonsterSkill.Skill.Effect, MapX, MapY, targetSession.Character.Hp > 0, (int)(targetSession.Character.Hp / targetSession.Character.HPLoad() * 100), damage, hitmode, 0) : StaticPacketHelper.SkillUsed(UserType.Monster, MapMonsterId, 1, Target, 0, Monster.BasicCooldown, 11, Monster.BasicSkill, 0, 0, targetSession.Character.Hp > 0, (int)(targetSession.Character.Hp / targetSession.Character.HPLoad() * 100), damage, hitmode, 0)); npcMonsterSkill?.Skill.BCards.ForEach(s => s.ApplyBCards(this)); LastSkill = DateTime.Now; if (targetSession.Character.Hp <= 0) { RemoveTarget(); Observable.Timer(TimeSpan.FromMilliseconds(1000)).Subscribe(o => ServerManager.Instance.AskRevive(targetSession?.Character?.CharacterId ?? 0)); } } if (npcMonsterSkill != null && (npcMonsterSkill.Skill.Range > 0 || npcMonsterSkill.Skill.TargetRange > 0)) { foreach (Character characterInRange in MapInstance.GetCharactersInRange(npcMonsterSkill.Skill.TargetRange == 0 ? MapX : targetSession.Character.PositionX, npcMonsterSkill.Skill.TargetRange == 0 ? MapY : targetSession.Character.PositionY, npcMonsterSkill.Skill.TargetRange).Where(s => s.CharacterId != Target && (ServerManager.Instance.ChannelId != 51 || MonsterVNum - (byte)s.Faction != 678) && s.Hp > 0 && !s.InvisibleGm)) { if (characterInRange.IsSitting) { characterInRange.IsSitting = false; MapInstance.Broadcast(characterInRange.GenerateRest()); } if (characterInRange.HasGodMode) { damage = 0; hitmode = 1; } if (characterInRange.Hp > 0) { characterInRange.GetDamage(damage); MapInstance.Broadcast(null, characterInRange.GenerateStat(), ReceiverType.OnlySomeone, string.Empty, characterInRange.CharacterId); MapInstance.Broadcast(StaticPacketHelper.SkillUsed(UserType.Monster, MapMonsterId, 1, characterInRange.CharacterId, 0, Monster.BasicCooldown, 11, Monster.BasicSkill, 0, 0, characterInRange.Hp > 0, (int)(characterInRange.Hp / characterInRange.HPLoad() * 100), damage, hitmode, 0)); if (characterInRange.Hp <= 0) { RemoveTarget(); Observable.Timer(TimeSpan.FromMilliseconds(1000)).Subscribe(o => ServerManager.Instance.AskRevive(characterInRange?.CharacterId ?? 0)); } } } } }
public void SpawnMeteorsOnRadius(byte radius, ClientSession session, Skill skill) { MapCell cell = Map.GetRandomPositionInRadius(radius, session.Character.PositionX, session.Character.PositionY); int meteorId = GetNextId(); if (cell == null) { return; } var meteor = new MapMonster { MonsterVNum = 2352, MapX = cell.X, MapY = cell.Y, MapMonsterId = meteorId, IsHostile = false, IsMoving = false, ShouldRespawn = false }; meteor.Initialize(this); AddMonster(meteor); Broadcast(meteor.GenerateIn()); Observable.Timer(TimeSpan.FromSeconds(2)).Subscribe(s => { Broadcast(StaticPacketHelper.SkillUsed(UserType.Monster, meteorId, 3, meteorId, 1337, 30, 0, (short)ServerManager.Instance.RandomNumber(4491, 4492), cell.X, cell.Y, true, 0, 0, -2, 0)); foreach (MapMonster monster in GetListMonsterInRange(meteor.MapX, meteor.MapY, (byte)(radius / 3))) { int hitmode = 0; bool onyx = false; int dmg = ServerManager.Instance.RandomNumber(500, 3000); if (monster.CurrentHp - dmg <= 0) { Broadcast(monster.GenerateOut()); monster.GenerateDeath(session.Character.BattleEntity.Entity); } } RemoveMonster(meteor); Broadcast(meteor.GenerateOut()); }); }
private void ExecuteHandler(ClientSession session) { if (_isParsed) { Logger.LogUserEvent("GMCOMMAND", session.GenerateIdentity(), $"[Kill]CharacterName: {CharacterName}"); ClientSession sess = ServerManager.Instance.GetSessionByCharacterName(CharacterName); if (sess != null) { if (sess.Character.HasGodMode) { return; } if (sess.Character.Hp < 1) { return; } sess.Character.Hp = 0; sess.Character.LastDefence = DateTime.UtcNow; session.CurrentMapInstance?.Broadcast(StaticPacketHelper.SkillUsed(UserType.Player, session.Character.CharacterId, 1, sess.Character.CharacterId, 1114, 4, 11, 4260, 0, 0, false, 0, 60000, 3, 0)); sess.SendPacket(sess.Character.GenerateStat()); ServerManager.Instance.AskRevive(sess.Character.CharacterId); session.SendPacket(session.Character.GenerateSay(Language.Instance.GetMessageFromKey("DONE"), 10)); } else { session.SendPacket( UserInterfaceHelper.GenerateMsg(Language.Instance.GetMessageFromKey("USER_NOT_CONNECTED"), 0)); } } else { session.SendPacket(session.Character.GenerateSay(ReturnHelp(), 10)); } }
private void spawnCircle(int round) { if (_map != null) { MapCell cell = _map.Map.GetRandomPosition(); int circleId = _map.GetNextMonsterId(); short[] monster = { 1, 1, 1, 1, 1 }; MapMonster circle = new MapMonster { MonsterVNum = monster[round], MapX = cell.X, MapY = cell.Y, MapMonsterId = circleId, IsHostile = false, IsMoving = false, ShouldRespawn = false }; circle.Initialize(_map); circle.NoAggresiveIcon = false; _map.AddMonster(circle); _map.Broadcast(circle.GenerateIn()); _map.Broadcast(StaticPacketHelper.GenerateEff(UserType.Monster, circleId, 4660)); if (_map != null) { _map.Broadcast(StaticPacketHelper.SkillUsed(UserType.Monster, circleId, 3, circleId, 1220, 220, 0, 4983, cell.X, cell.Y, true, 0, 65535, 0, 0)); foreach (Character character in _map.GetCharactersInRange(cell.X, cell.Y, 2)) { if (!_map.Sessions.Skip(3).Any()) { //Regalo para los 3 ultimos supervivientes. character.Inventory.AddNewToInventory(1, 1).FirstOrDefault(); } character.IsCustomSpeed = false; character.RemoveVehicle(); Observable.Timer(TimeSpan.FromMilliseconds(1000)).Subscribe(o => ServerManager.Instance.AskRevive(character.CharacterId)); } _map.Broadcast(StaticPacketHelper.Out(UserType.Monster, circle.MapMonsterId)); } } }
public void ApplyBCards(object session, object sender = null) { Type type = session.GetType(); // int counterBuff = 0; if (type == null) { return; } switch ((BCardType.CardType)Type) { case BCardType.CardType.Buff: { if (type == typeof(Character) && session is Character character) { Buff buff = null; if (sender != null) { Type sType = sender.GetType(); if (sType != null) { if (sType == typeof(Character) && sender is Character sendingCharacter) { buff = new Buff((short)SecondData, sendingCharacter.Level); //Todo: Get anti stats from BCard } } } else { buff = new Buff((short)SecondData, character.Level); } if (ServerManager.RandomNumber() < FirstData) { character.AddBuff(buff); } } else if (type == typeof(MapMonster)) { if (ServerManager.RandomNumber() < FirstData && session is MapMonster mapMonster) { mapMonster.AddBuff(new Buff((short)SecondData, mapMonster.Monster.Level)); } } else if (type == typeof(MapNpc)) { } else if (type == typeof(Mate)) { } break; } case BCardType.CardType.Move: { if (type == typeof(Character) && session is Character character) { character.LastSpeedChange = DateTime.Now; character.Session.SendPacket(character.GenerateCond()); } } break; case BCardType.CardType.Summons: if (type == typeof(Character)) { } else if (type == typeof(MapMonster)) { if (session is MapMonster mapMonster) { List <MonsterToSummon> summonParameters = new List <MonsterToSummon>(); for (int i = 0; i < FirstData; i++) { short x = (short)(ServerManager.RandomNumber(-3, 3) + mapMonster.MapX); short y = (short)(ServerManager.RandomNumber(-3, 3) + mapMonster.MapY); summonParameters.Add(new MonsterToSummon((short)SecondData, new MapCell { X = x, Y = y }, -1, true)); } if (ServerManager.RandomNumber() <= Math.Abs(ThirdData) || ThirdData == 0) { switch (SubType) { case 2: EventHelper.Instance.RunEvent(new EventContainer(mapMonster.MapInstance, EventActionType.SPAWNMONSTERS, summonParameters)); break; default: if (!mapMonster.OnDeathEvents.Any(s => s.EventActionType == EventActionType.SPAWNMONSTERS)) { mapMonster.OnDeathEvents.Add(new EventContainer(mapMonster.MapInstance, EventActionType.SPAWNMONSTERS, summonParameters)); } break; } } } } else if (type == typeof(MapNpc)) { } else if (type == typeof(Mate)) { } break; case BCardType.CardType.SpecialAttack: break; case BCardType.CardType.SpecialDefence: break; case BCardType.CardType.AttackPower: break; case BCardType.CardType.Target: break; case BCardType.CardType.Critical: break; case BCardType.CardType.SpecialCritical: break; case BCardType.CardType.Element: break; case BCardType.CardType.IncreaseDamage: break; case BCardType.CardType.Defence: break; case BCardType.CardType.DodgeAndDefencePercent: break; case BCardType.CardType.Block: break; case BCardType.CardType.Absorption: break; case BCardType.CardType.ElementResistance: break; case BCardType.CardType.EnemyElementResistance: break; case BCardType.CardType.Damage: break; case BCardType.CardType.GuarantedDodgeRangedAttack: break; case BCardType.CardType.Morale: break; case BCardType.CardType.Casting: break; case BCardType.CardType.Reflection: break; case BCardType.CardType.DrainAndSteal: break; case BCardType.CardType.HealingBurningAndCasting: if (type == typeof(Character)) { if (session is Character character && character.Hp > 0) { int bonus = 0; if (SubType == (byte)AdditionalTypes.HealingBurningAndCasting.RestoreHP / 10) { if (IsLevelScaled) { bonus = character.Level * FirstData; } else { bonus = FirstData; } if (character.Hp + bonus <= character.HPLoad()) { character.Hp += bonus; } else { bonus = (int)character.HPLoad() - character.Hp; character.Hp = (int)character.HPLoad(); } character.Session.CurrentMapInstance?.Broadcast(character.Session, character.GenerateRc(bonus)); } if (SubType == (byte)AdditionalTypes.HealingBurningAndCasting.RestoreMP / 10) { if (IsLevelScaled) { bonus = character.Level * FirstData; } else { bonus = FirstData; } if (character.Mp + bonus <= character.MPLoad()) { character.Mp += bonus; } else { bonus = (int)character.MPLoad() - character.Mp; character.Mp = (int)character.MPLoad(); } } character.Session.SendPacket(character.GenerateStat()); } } else if (type == typeof(MapMonster)) { if (ServerManager.RandomNumber() < FirstData && session is MapMonster mapMonster) { mapMonster.AddBuff(new Buff((short)SecondData, mapMonster.Monster.Level)); } } else if (type == typeof(MapNpc)) { } else if (type == typeof(Mate)) { } break; case BCardType.CardType.HPMP: break; case BCardType.CardType.SpecialisationBuffResistance: break; case BCardType.CardType.SpecialEffects: break; case BCardType.CardType.Capture: if (type == typeof(MapMonster)) { if (session is MapMonster mapMonster && sender is ClientSession senderSession) { NpcMonster mateNpc = ServerManager.GetNpc(mapMonster.MonsterVNum); if (mateNpc != null) { if (mapMonster.Monster.Catch) { if (mapMonster.IsAlive && mapMonster.CurrentHp <= (int)((double)mapMonster.MaxHp / 2)) { if (mapMonster.Monster.Level < senderSession.Character.Level) { #warning find a new algorithm int[] chance = { 100, 80, 60, 40, 20, 0 }; if (ServerManager.RandomNumber() < chance[ServerManager.RandomNumber(0, 5)]) { Mate mate = new Mate(senderSession.Character, mateNpc, (byte)(mapMonster.Monster.Level - 15 > 0 ? mapMonster.Monster.Level - 15 : 1), MateType.Pet); if (senderSession.Character.CanAddMate(mate)) { senderSession.Character.AddPetWithSkill(mate); senderSession.SendPacket(UserInterfaceHelper.GenerateMsg(Language.Instance.GetMessageFromKey("CATCH_SUCCESS"), 0)); senderSession.CurrentMapInstance?.Broadcast(StaticPacketHelper.GenerateEff(UserType.Player, senderSession.Character.CharacterId, 197)); senderSession.CurrentMapInstance?.Broadcast(StaticPacketHelper.SkillUsed(UserType.Player, senderSession.Character.CharacterId, 3, mapMonster.MapMonsterId, -1, 0, 15, -1, -1, -1, true, (int)((float)mapMonster.CurrentHp / (float)mapMonster.MaxHp * 100), 0, -1, 0)); mapMonster.SetDeathStatement(); senderSession.CurrentMapInstance?.Broadcast(StaticPacketHelper.Out(UserType.Monster, mapMonster.MapMonsterId)); } else { senderSession.SendPacket(senderSession.Character.GenerateSay(Language.Instance.GetMessageFromKey("PET_SLOT_FULL"), 10)); senderSession.SendPacket(StaticPacketHelper.Cancel(2, mapMonster.MapMonsterId)); } } else { senderSession.SendPacket(UserInterfaceHelper.GenerateMsg(Language.Instance.GetMessageFromKey("CATCH_FAIL"), 0)); senderSession.CurrentMapInstance?.Broadcast(StaticPacketHelper.SkillUsed(UserType.Player, senderSession.Character.CharacterId, 3, mapMonster.MapMonsterId, -1, 0, 15, -1, -1, -1, true, (int)((float)mapMonster.CurrentHp / (float)mapMonster.MaxHp * 100), 0, -1, 0)); } } else { senderSession.SendPacket(UserInterfaceHelper.GenerateMsg(Language.Instance.GetMessageFromKey("LEVEL_LOWER_THAN_MONSTER"), 0)); senderSession.SendPacket(StaticPacketHelper.Cancel(2, mapMonster.MapMonsterId)); } } else { senderSession.SendPacket(UserInterfaceHelper.GenerateMsg(Language.Instance.GetMessageFromKey("CURRENT_HP_TOO_HIGH"), 0)); senderSession.SendPacket(StaticPacketHelper.Cancel(2, mapMonster.MapMonsterId)); } } else { senderSession.SendPacket(UserInterfaceHelper.GenerateMsg(Language.Instance.GetMessageFromKey("MONSTER_CANT_BE_CAPTURED"), 0)); senderSession.SendPacket(StaticPacketHelper.Cancel(2, mapMonster.MapMonsterId)); } } } } break; case BCardType.CardType.SpecialDamageAndExplosions: break; case BCardType.CardType.SpecialEffects2: break; case BCardType.CardType.CalculatingLevel: break; case BCardType.CardType.Recovery: break; case BCardType.CardType.MaxHPMP: break; case BCardType.CardType.MultAttack: break; case BCardType.CardType.MultDefence: break; case BCardType.CardType.TimeCircleSkills: break; case BCardType.CardType.RecoveryAndDamagePercent: break; case BCardType.CardType.Count: break; case BCardType.CardType.NoDefeatAndNoDamage: break; case BCardType.CardType.SpecialActions: break; case BCardType.CardType.Mode: break; case BCardType.CardType.NoCharacteristicValue: break; case BCardType.CardType.LightAndShadow: break; case BCardType.CardType.Item: break; case BCardType.CardType.DebuffResistance: break; case BCardType.CardType.SpecialBehaviour: break; case BCardType.CardType.Quest: break; case BCardType.CardType.SecondSPCard: break; case BCardType.CardType.SPCardUpgrade: break; case BCardType.CardType.HugeSnowman: break; case BCardType.CardType.Drain: break; case BCardType.CardType.BossMonstersSkill: break; case BCardType.CardType.LordHatus: break; case BCardType.CardType.LordCalvinas: break; case BCardType.CardType.SESpecialist: break; case BCardType.CardType.FourthGlacernonFamilyRaid: break; case BCardType.CardType.SummonedMonsterAttack: break; case BCardType.CardType.BearSpirit: break; case BCardType.CardType.SummonSkill: break; case BCardType.CardType.InflictSkill: break; case BCardType.CardType.HideBarrelSkill: break; case BCardType.CardType.FocusEnemyAttentionSkill: break; case BCardType.CardType.TauntSkill: break; case BCardType.CardType.FireCannoneerRangeBuff: break; case BCardType.CardType.VulcanoElementBuff: break; case BCardType.CardType.DamageConvertingSkill: break; case BCardType.CardType.MeditationSkill: { if (type == typeof(Character) && session is Character character) { if (SkillVNum.HasValue && SubType.Equals((byte)AdditionalTypes.MeditationSkill.CausingChance / 10) && ServerManager.RandomNumber() < FirstData) { Skill skill = ServerManager.GetSkill(SkillVNum.Value); Skill newSkill = ServerManager.GetSkill((short)SecondData); Observable.Timer(TimeSpan.FromMilliseconds(100)).Subscribe(observer => { foreach (QuicklistEntryDTO quicklistEntry in character.QuicklistEntries.Where(s => s.Pos.Equals(skill.CastId))) { character.Session.SendPacket($"qset {quicklistEntry.Q1} {quicklistEntry.Q2} {quicklistEntry.Type}.{quicklistEntry.Slot}.{newSkill.CastId}.0"); } character.Session.SendPacket($"mslot {newSkill.CastId} -1"); }); character.SkillComboCount++; character.LastSkillComboUse = DateTime.Now; if (skill.CastId > 10) { // HACK this way Observable.Timer(TimeSpan.FromMilliseconds((skill.Cooldown * 100) + 500)).Subscribe(observer => character.Session.SendPacket(StaticPacketHelper.SkillReset(skill.CastId))); } } switch (SubType) { case 2: character.MeditationDictionary[(short)SecondData] = DateTime.Now.AddSeconds(4); break; case 3: character.MeditationDictionary[(short)SecondData] = DateTime.Now.AddSeconds(8); break; case 4: character.MeditationDictionary[(short)SecondData] = DateTime.Now.AddSeconds(12); break; } } } break; case BCardType.CardType.FalconSkill: break; case BCardType.CardType.AbsorptionAndPowerSkill: break; case BCardType.CardType.LeonaPassiveSkill: break; case BCardType.CardType.FearSkill: break; case BCardType.CardType.SniperAttack: break; case BCardType.CardType.FrozenDebuff: break; case BCardType.CardType.JumpBackPush: break; case BCardType.CardType.FairyXPIncrease: break; case BCardType.CardType.SummonAndRecoverHP: break; case BCardType.CardType.TeamArenaBuff: break; case BCardType.CardType.ArenaCamera: break; case BCardType.CardType.DarkCloneSummon: break; case BCardType.CardType.AbsorbedSpirit: break; case BCardType.CardType.AngerSkill: break; case BCardType.CardType.MeteoriteTeleport: break; case BCardType.CardType.StealBuff: break; case BCardType.CardType.Unknown: break; case BCardType.CardType.EffectSummon: break; default: Logger.Warn($"Card Type {Type} not defined!"); break; } }
private void npcLife() { // Respawn if (CurrentHp <= 0 && ShouldRespawn != null && !ShouldRespawn.Value) { MapInstance.RemoveNpc(this); MapInstance.Broadcast(GenerateOut()); } if (!IsAlive && ShouldRespawn != null && ShouldRespawn.Value) { double timeDeath = (DateTime.Now - Death).TotalSeconds; if (timeDeath >= Npc.RespawnTime / 10d) { Respawn(); } } if (LastProtectedEffect.AddMilliseconds(6000) <= DateTime.Now) { LastProtectedEffect = DateTime.Now; if (IsMate || IsProtected) { MapInstance.Broadcast(StaticPacketHelper.GenerateEff(UserType.Npc, MapNpcId, 825), MapX, MapY); } } double time = (DateTime.Now - LastEffect).TotalMilliseconds; if (EffectDelay > 0) { if (time > EffectDelay) { if (Effect > 0 && EffectActivated) { MapInstance.Broadcast(StaticPacketHelper.GenerateEff(UserType.Npc, MapNpcId, Effect), MapX, MapY); } LastEffect = DateTime.Now; } } time = (DateTime.Now - LastMove).TotalMilliseconds; if (Target == -1 && IsMoving && Npc.Speed > 0 && time > _movetime && !HasBuff(CardType.Move, (byte)AdditionalTypes.Move.MovementImpossible)) { _movetime = ServerManager.RandomNumber(500, 3000); int maxindex = Path.Count > Npc.Speed / 2 && Npc.Speed > 1 ? Npc.Speed / 2 : Path.Count; if (maxindex < 1) { maxindex = 1; } if (Path.Count == 0 || Path.Count >= maxindex && maxindex > 0 && Path[maxindex - 1] == null) { short xoffset = (short)ServerManager.RandomNumber(-1, 1); short yoffset = (short)ServerManager.RandomNumber(-1, 1); MapCell moveToPosition = new MapCell { X = FirstX, Y = FirstY }; if (RunToX != 0 || RunToY != 0) { moveToPosition = new MapCell { X = RunToX, Y = RunToY }; _movetime = ServerManager.RandomNumber(300, 1200); } Path = BestFirstSearch.FindPathJagged(new GridPos { X = MapX, Y = MapY }, new GridPos { X = (short)ServerManager.RandomNumber(moveToPosition.X - 3, moveToPosition.X + 3), Y = (short)ServerManager.RandomNumber(moveToPosition.Y - 3, moveToPosition.Y + 3) }, MapInstance.Map.JaggedGrid); maxindex = Path.Count > Npc.Speed / 2 && Npc.Speed > 1 ? Npc.Speed / 2 : Path.Count; } if (DateTime.Now > LastMove && Npc.Speed > 0 && Path.Count > 0) { byte speedIndex = (byte)(Npc.Speed / 2.5 < 1 ? 1 : Npc.Speed / 2.5); maxindex = Path.Count > speedIndex ? speedIndex : Path.Count; short mapX = (short)ServerManager.RandomNumber(Path[maxindex - 1].X - 1, Path[maxindex - 1].X + 1); short mapY = (short)_random.Next(Path[maxindex - 1].Y - 1, Path[maxindex - 1].Y + 1); //short mapX = Path[maxindex - 1].X; //short mapY = Path[maxindex - 1].Y; double waitingtime = Map.GetDistance(new MapCell { X = mapX, Y = mapY }, new MapCell { X = MapX, Y = MapY }) / (double)Npc.Speed; MapInstance.Broadcast(new BroadcastPacket(null, PacketFactory.Serialize(StaticPacketHelper.Move(UserType.Npc, MapNpcId, mapX, mapY, Npc.Speed)), ReceiverType.All, xCoordinate: mapX, yCoordinate: mapY)); LastMove = DateTime.Now.AddSeconds(waitingtime > 1 ? 1 : waitingtime); Observable.Timer(TimeSpan.FromMilliseconds((int)((waitingtime > 1 ? 1 : waitingtime) * 1000))).Subscribe(x => { MapX = mapX; MapY = mapY; }); Path.RemoveRange(0, maxindex); } } if (Target == -1) { if (IsHostile && Shop == null) { MapMonster monster = MapInstance.GetMonsterInRangeList(MapX, MapY, (byte)(Npc.NoticeRange > 5 ? Npc.NoticeRange / 2 : Npc.NoticeRange)).Where(s => BattleEntity.CanAttackEntity(s.BattleEntity)).FirstOrDefault(); ClientSession session = MapInstance.Sessions.FirstOrDefault(s => BattleEntity.CanAttackEntity(s.Character.BattleEntity) && MapInstance == s.Character.MapInstance && Map.GetDistance(new MapCell { X = MapX, Y = MapY }, new MapCell { X = s.Character.PositionX, Y = s.Character.PositionY }) < Npc.NoticeRange); if (monster != null) { Target = monster.MapMonsterId; } if (session?.Character != null) { Target = session.Character.CharacterId; } } } else if (Target != -1) { MapMonster monster = MapInstance.Monsters.Find(s => s.MapMonsterId == Target); if (monster == null || monster.CurrentHp < 1) { Target = -1; return; } NpcMonsterSkill npcMonsterSkill = null; if (ServerManager.RandomNumber(0, 10) > 8) { npcMonsterSkill = Skills.Where(s => (DateTime.Now - s.LastSkillUse).TotalMilliseconds >= 100 * s.Skill.Cooldown).OrderBy(rnd => _random.Next()).FirstOrDefault(); } int hitmode = 0; bool onyxWings = false; int damage = DamageHelper.Instance.CalculateDamage(new BattleEntity(this), new BattleEntity(monster), npcMonsterSkill?.Skill, ref hitmode, ref onyxWings); if (monster.Monster.BCards.Find(s => s.Type == (byte)CardType.LightAndShadow && s.SubType == (byte)AdditionalTypes.LightAndShadow.InflictDamageToMP) is BCard card) { int reduce = damage / 100 * card.FirstData; if (monster.CurrentMp < reduce) { reduce = (int)monster.CurrentMp; monster.CurrentMp = 0; } else { monster.DecreaseMp(reduce); } damage -= reduce; } int distance = Map.GetDistance(new MapCell { X = MapX, Y = MapY }, new MapCell { X = monster.MapX, Y = monster.MapY }); if (monster.CurrentHp > 0 && ((npcMonsterSkill != null && distance < npcMonsterSkill.Skill.Range) || distance <= Npc.BasicRange) && !HasBuff(CardType.SpecialAttack, (byte)AdditionalTypes.SpecialAttack.NoAttack)) { if (((DateTime.Now - LastSkill).TotalMilliseconds >= 1000 + (Npc.BasicCooldown * 200) /* && Skills.Count == 0*/) || npcMonsterSkill != null) { if (npcMonsterSkill != null) { npcMonsterSkill.LastSkillUse = DateTime.Now; MapInstance.Broadcast(StaticPacketHelper.CastOnTarget(UserType.Npc, MapNpcId, UserType.Monster, Target, npcMonsterSkill.Skill.CastAnimation, npcMonsterSkill.Skill.CastEffect, npcMonsterSkill.Skill.SkillVNum)); } if (npcMonsterSkill != null && npcMonsterSkill.Skill.CastEffect != 0) { MapInstance.Broadcast(StaticPacketHelper.GenerateEff(UserType.Npc, MapNpcId, Effect)); } monster.BattleEntity.GetDamage(damage, BattleEntity); lock (monster.DamageList) { if (!monster.DamageList.Any(s => s.Key.MapEntityId == MapNpcId)) { monster.AddToAggroList(BattleEntity); } } MapInstance.Broadcast(npcMonsterSkill != null ? StaticPacketHelper.SkillUsed(UserType.Npc, MapNpcId, 3, Target, npcMonsterSkill.SkillVNum, npcMonsterSkill.Skill.Cooldown, npcMonsterSkill.Skill.AttackAnimation, npcMonsterSkill.Skill.Effect, 0, 0, monster.CurrentHp > 0, (int)((float)monster.CurrentHp / (float)monster.MaxHp * 100), damage, hitmode, 0) : StaticPacketHelper.SkillUsed(UserType.Npc, MapNpcId, 3, Target, 0, Npc.BasicCooldown, 11, Npc.BasicSkill, 0, 0, monster.CurrentHp > 0, (int)((float)monster.CurrentHp / (float)monster.MaxHp * 100), damage, hitmode, 0)); LastSkill = DateTime.Now; if (npcMonsterSkill?.Skill.TargetType == 1 && npcMonsterSkill?.Skill.HitType == 2) { IEnumerable <ClientSession> clientSessions = MapInstance.Sessions?.Where(s => s.Character.IsInRange(MapX, MapY, npcMonsterSkill.Skill.TargetRange)); IEnumerable <Mate> mates = MapInstance.GetListMateInRange(MapX, MapY, npcMonsterSkill.Skill.TargetRange); foreach (BCard skillBcard in npcMonsterSkill.Skill.BCards) { if (skillBcard.Type == 25 && skillBcard.SubType == 1 && new Buff((short)skillBcard.SecondData, Npc.Level)?.Card?.BuffType == BuffType.Good) { if (clientSessions != null) { foreach (ClientSession clientSession in clientSessions) { if (clientSession.Character != null) { if (!BattleEntity.CanAttackEntity(clientSession.Character.BattleEntity)) { skillBcard.ApplyBCards(clientSession.Character.BattleEntity, BattleEntity); } } } } if (mates != null) { foreach (Mate mate in mates) { if (!BattleEntity.CanAttackEntity(mate.BattleEntity)) { skillBcard.ApplyBCards(mate.BattleEntity, BattleEntity); } } } } } } if (monster.CurrentHp < 1 && monster.SetDeathStatement()) { monster.RunDeathEvent(); RemoveTarget(); } } } else { int maxdistance = Npc.NoticeRange > 5 ? Npc.NoticeRange / 2 : Npc.NoticeRange; if (IsMoving && !HasBuff(CardType.Move, (byte)AdditionalTypes.Move.MovementImpossible)) { const short maxDistance = 5; int maxindex = Path.Count > Npc.Speed / 2 && Npc.Speed > 1 ? Npc.Speed / 2 : Path.Count; if (maxindex < 1) { maxindex = 1; } if ((Path.Count == 0 && distance >= 1 && distance < maxDistance) || (Path.Count >= maxindex && maxindex > 0 && Path[maxindex - 1] == null)) { short xoffset = (short)ServerManager.RandomNumber(-1, 1); short yoffset = (short)ServerManager.RandomNumber(-1, 1); //go to monster Path = BestFirstSearch.FindPathJagged(new GridPos { X = MapX, Y = MapY }, new GridPos { X = (short)(monster.MapX + xoffset), Y = (short)(monster.MapY + yoffset) }, MapInstance.Map.JaggedGrid); maxindex = Path.Count > Npc.Speed / 2 && Npc.Speed > 1 ? Npc.Speed / 2 : Path.Count; } if (DateTime.Now > LastMove && Npc.Speed > 0 && Path.Count > 0) { byte speedIndex = (byte)(Npc.Speed / 2.5 < 1 ? 1 : Npc.Speed / 2.5); maxindex = Path.Count > speedIndex ? speedIndex : Path.Count; //short mapX = (short)ServerManager.RandomNumber(Path[maxindex - 1].X - 1, Path[maxindex - 1].X + 1); //short mapY = (short)_random.Next(Path[maxindex - 1].Y - 1, Path[maxindex - 1].Y + 1); short mapX = Path[maxindex - 1].X; short mapY = Path[maxindex - 1].Y; double waitingtime = Map.GetDistance(new MapCell { X = mapX, Y = mapY }, new MapCell { X = MapX, Y = MapY }) / (double)Npc.Speed; MapInstance.Broadcast(new BroadcastPacket(null, PacketFactory.Serialize(StaticPacketHelper.Move(UserType.Npc, MapNpcId, mapX, mapY, Npc.Speed)), ReceiverType.All, xCoordinate: mapX, yCoordinate: mapY)); LastMove = DateTime.Now.AddSeconds(waitingtime > 1 ? 1 : waitingtime); Observable.Timer(TimeSpan.FromMilliseconds((int)((waitingtime > 1 ? 1 : waitingtime) * 1000))).Subscribe(x => { MapX = mapX; MapY = mapY; }); Path.RemoveRange(0, maxindex); } if (Target != -1 && (MapId != monster.MapId || distance > maxDistance)) { RemoveTarget(); } } } } }
private void npcLife() { double time = (DateTime.Now - LastEffect).TotalMilliseconds; if (time > EffectDelay) { if (IsMate || IsProtected) { MapInstance.Broadcast(StaticPacketHelper.GenerateEff(UserType.Npc, MapNpcId, 825), MapX, MapY); } if (Effect > 0 && EffectActivated) { MapInstance.Broadcast(StaticPacketHelper.GenerateEff(UserType.Npc, MapNpcId, Effect), MapX, MapY); } LastEffect = DateTime.Now; } time = (DateTime.Now - LastMove).TotalMilliseconds; if (IsMoving && Npc.Speed > 0 && time > _movetime) { _movetime = ServerManager.RandomNumber(500, 3000); byte point = (byte)ServerManager.RandomNumber(2, 4); byte fpoint = (byte)ServerManager.RandomNumber(0, 2); byte xpoint = (byte)ServerManager.RandomNumber(fpoint, point); byte ypoint = (byte)(point - xpoint); short mapX = FirstX; short mapY = FirstY; if (MapInstance.Map.GetFreePosition(ref mapX, ref mapY, xpoint, ypoint)) { double value = (xpoint + ypoint) / (double)(2 * Npc.Speed); Observable.Timer(TimeSpan.FromMilliseconds(1000 * value)).Subscribe(x => { MapX = mapX; MapY = mapY; }); LastMove = DateTime.Now.AddSeconds(value); MapInstance.Broadcast(new BroadcastPacket(null, PacketFactory.Serialize(StaticPacketHelper.Move(UserType.Npc, MapNpcId, MapX, MapY, Npc.Speed)), ReceiverType.All, xCoordinate: mapX, yCoordinate: mapY)); } } if (Target == -1) { if (IsHostile && Shop == null) { MapMonster monster = MapInstance.Monsters.Find(s => MapInstance == s.MapInstance && Map.GetDistance(new MapCell { X = MapX, Y = MapY }, new MapCell { X = s.MapX, Y = s.MapY }) < (Npc.NoticeRange > 5 ? Npc.NoticeRange / 2 : Npc.NoticeRange)); ClientSession session = MapInstance.Sessions.FirstOrDefault(s => MapInstance == s.Character.MapInstance && Map.GetDistance(new MapCell { X = MapX, Y = MapY }, new MapCell { X = s.Character.PositionX, Y = s.Character.PositionY }) < Npc.NoticeRange); if (monster != null && session != null) { Target = monster.MapMonsterId; } } } else if (Target != -1) { MapMonster monster = MapInstance.Monsters.Find(s => s.MapMonsterId == Target); if (monster == null || monster.CurrentHp < 1) { Target = -1; return; } NpcMonsterSkill npcMonsterSkill = null; if (ServerManager.RandomNumber(0, 10) > 8) { npcMonsterSkill = Npc.Skills.Where(s => (DateTime.Now - s.LastSkillUse).TotalMilliseconds >= 100 * s.Skill.Cooldown).OrderBy(rnd => _random.Next()).FirstOrDefault(); } int hitmode = 0; bool onyxWings = false; int damage = DamageHelper.Instance.CalculateDamage(new BattleEntity(this), new BattleEntity(monster), npcMonsterSkill?.Skill, ref hitmode, ref onyxWings); if (monster.Monster.BCards.Find(s => s.Type == (byte)CardType.LightAndShadow && s.SubType == (byte)AdditionalTypes.LightAndShadow.InflictDamageToMP) is BCard card) { int reduce = damage / 100 * card.FirstData; if (monster.CurrentMp < reduce) { monster.CurrentMp = 0; } else { monster.CurrentMp -= reduce; } } int distance = Map.GetDistance(new MapCell { X = MapX, Y = MapY }, new MapCell { X = monster.MapX, Y = monster.MapY }); if (monster.CurrentHp > 0 && ((npcMonsterSkill != null && distance < npcMonsterSkill.Skill.Range) || distance <= Npc.BasicRange)) { if (((DateTime.Now - LastEffect).TotalMilliseconds >= 1000 + (Npc.BasicCooldown * 200) && Npc.Skills.Count == 0) || npcMonsterSkill != null) { if (npcMonsterSkill != null) { npcMonsterSkill.LastSkillUse = DateTime.Now; MapInstance.Broadcast(StaticPacketHelper.CastOnTarget(UserType.Npc, MapNpcId, 3, Target, npcMonsterSkill.Skill.CastAnimation, npcMonsterSkill.Skill.CastEffect, npcMonsterSkill.Skill.SkillVNum)); } if (npcMonsterSkill != null && npcMonsterSkill.Skill.CastEffect != 0) { MapInstance.Broadcast(StaticPacketHelper.GenerateEff(UserType.Npc, MapNpcId, Effect)); } monster.CurrentHp -= damage; MapInstance.Broadcast(npcMonsterSkill != null ? StaticPacketHelper.SkillUsed(UserType.Npc, MapNpcId, 3, Target, npcMonsterSkill.SkillVNum, npcMonsterSkill.Skill.Cooldown, npcMonsterSkill.Skill.AttackAnimation, npcMonsterSkill.Skill.Effect, 0, 0, monster.CurrentHp > 0, (int)((float)monster.CurrentHp / (float)monster.Monster.MaxHP * 100), damage, hitmode, 0) : StaticPacketHelper.SkillUsed(UserType.Npc, MapNpcId, 3, Target, 0, Npc.BasicCooldown, 11, Npc.BasicSkill, 0, 0, monster.CurrentHp > 0, (int)((float)monster.CurrentHp / (float)monster.Monster.MaxHP * 100), damage, hitmode, 0)); LastEffect = DateTime.Now; if (monster.CurrentHp < 1) { RemoveTarget(); monster.IsAlive = false; monster.LastMove = DateTime.Now; monster.CurrentHp = 0; monster.CurrentMp = 0; monster.Death = DateTime.Now; Target = -1; } } } else { int maxdistance = Npc.NoticeRange > 5 ? Npc.NoticeRange / 2 : Npc.NoticeRange; if (IsMoving) { const short maxDistance = 5; int maxindex = Path.Count > Npc.Speed / 2 && Npc.Speed > 1 ? Npc.Speed / 2 : Path.Count; if (maxindex < 1) { maxindex = 1; } if ((Path.Count == 0 && distance >= 1 && distance < maxDistance) || (Path.Count >= maxindex && maxindex > 0 && Path[maxindex - 1] == null)) { short xoffset = (short)ServerManager.RandomNumber(-1, 1); short yoffset = (short)ServerManager.RandomNumber(-1, 1); //go to monster Path = BestFirstSearch.FindPathJagged(new GridPos { X = MapX, Y = MapY }, new GridPos { X = (short)(monster.MapX + xoffset), Y = (short)(monster.MapY + yoffset) }, MapInstance.Map.JaggedGrid); maxindex = Path.Count > Npc.Speed / 2 && Npc.Speed > 1 ? Npc.Speed / 2 : Path.Count; } if (DateTime.Now > LastMove && Npc.Speed > 0 && Path.Count > 0) { short mapX = Path[maxindex - 1].X; short mapY = Path[maxindex - 1].Y; double waitingtime = Map.GetDistance(new MapCell { X = mapX, Y = mapY }, new MapCell { X = MapX, Y = MapY }) / (double)Npc.Speed; MapInstance.Broadcast(new BroadcastPacket(null, PacketFactory.Serialize(StaticPacketHelper.Move(UserType.Npc, MapNpcId, MapX, MapY, Npc.Speed)), ReceiverType.All, xCoordinate: mapX, yCoordinate: mapY)); LastMove = DateTime.Now.AddSeconds(waitingtime > 1 ? 1 : waitingtime); Observable.Timer(TimeSpan.FromMilliseconds((int)((waitingtime > 1 ? 1 : waitingtime) * 1000))).Subscribe(x => { MapX = mapX; MapY = mapY; }); Path.RemoveRange(0, maxindex); } if (Target != -1 && (MapId != monster.MapId || distance > maxDistance)) { RemoveTarget(); } } } } }
/// <summary> /// Handle any kind of Monster interaction /// </summary> private void monsterLife() { if (Monster == null) { return; } if ((DateTime.Now - LastEffect).TotalSeconds >= 5) { LastEffect = DateTime.Now; if (IsTarget) { MapInstance.Broadcast(StaticPacketHelper.GenerateEff(UserType.Monster, MapMonsterId, 824)); } if (IsBonus) { MapInstance.Broadcast(StaticPacketHelper.GenerateEff(UserType.Monster, MapMonsterId, 826)); } } if (IsBoss && IsAlive) { MapInstance.Broadcast(GenerateBoss()); } // handle hit queue while (HitQueue.TryDequeue(out HitRequest hitRequest)) { if (IsAlive && hitRequest.Session.Character.Hp > 0 && (ServerManager.Instance.ChannelId != 51 || MonsterVNum - (byte)hitRequest.Session.Character.Faction != 678)) { int hitmode = 0; bool isCaptureSkill = hitRequest.Skill.BCards.Any(s => s.Type.Equals((byte)CardType.Capture)); // calculate damage bool onyxWings = false; BattleEntity battleEntity = new BattleEntity(hitRequest.Session.Character, hitRequest.Skill); int damage = DamageHelper.Instance.CalculateDamage(battleEntity, new BattleEntity(this), hitRequest.Skill, ref hitmode, ref onyxWings); if (onyxWings) { short onyxX = (short)(hitRequest.Session.Character.PositionX + 2); short onyxY = (short)(hitRequest.Session.Character.PositionY + 2); int onyxId = MapInstance.GetNextMonsterId(); MapMonster onyx = new MapMonster() { MonsterVNum = 2371, MapX = onyxX, MapY = onyxY, MapMonsterId = onyxId, IsHostile = false, IsMoving = false, ShouldRespawn = false }; MapInstance.Broadcast(UserInterfaceHelper.Instance.GenerateGuri(31, 1, hitRequest.Session.Character.CharacterId, onyxX, onyxY)); onyx.Initialize(MapInstance); MapInstance.AddMonster(onyx); MapInstance.Broadcast(onyx.GenerateIn()); CurrentHp -= damage / 2; Observable.Timer(TimeSpan.FromMilliseconds(350)).Subscribe(o => { MapInstance.Broadcast(StaticPacketHelper.SkillUsed(UserType.Monster, onyxId, 3, MapMonsterId, -1, 0, -1, hitRequest.Skill.Effect, -1, -1, true, 92, damage / 2, 0, 0)); MapInstance.RemoveMonster(onyx); MapInstance.Broadcast(StaticPacketHelper.Out(UserType.Monster, onyx.MapMonsterId)); }); } if (hitmode != 1) { hitRequest.Skill.BCards.Where(s => s.Type.Equals((byte)CardType.Buff)).ToList().ForEach(s => s.ApplyBCards(this, hitRequest.Session)); hitRequest.Skill.BCards.Where(s => s.Type.Equals((byte)CardType.Capture)).ToList().ForEach(s => s.ApplyBCards(this, hitRequest.Session)); if (battleEntity?.ShellWeaponEffects != null) { foreach (ShellEffectDTO shell in battleEntity.ShellWeaponEffects) { switch (shell.Effect) { case (byte)ShellWeaponEffectType.Blackout: { Buff buff = new Buff(7, battleEntity.Level); if (ServerManager.Instance.RandomNumber() < shell.Value) { AddBuff(buff); } break; } case (byte)ShellWeaponEffectType.DeadlyBlackout: { Buff buff = new Buff(66, battleEntity.Level); if (ServerManager.Instance.RandomNumber() < shell.Value) { AddBuff(buff); } break; } case (byte)ShellWeaponEffectType.MinorBleeding: { Buff buff = new Buff(1, battleEntity.Level); if (ServerManager.Instance.RandomNumber() < shell.Value) { AddBuff(buff); } break; } case (byte)ShellWeaponEffectType.Bleeding: { Buff buff = new Buff(21, battleEntity.Level); if (ServerManager.Instance.RandomNumber() < shell.Value) { AddBuff(buff); } break; } case (byte)ShellWeaponEffectType.HeavyBleeding: { Buff buff = new Buff(42, battleEntity.Level); if (ServerManager.Instance.RandomNumber() < shell.Value) { AddBuff(buff); } break; } case (byte)ShellWeaponEffectType.Freeze: { Buff buff = new Buff(27, battleEntity.Level); if (ServerManager.Instance.RandomNumber() < shell.Value) { AddBuff(buff); } break; } } } } } if (DamageList.ContainsKey(hitRequest.Session.Character.CharacterId)) { DamageList[hitRequest.Session.Character.CharacterId] += damage; } else { DamageList.Add(hitRequest.Session.Character.CharacterId, damage); } if (isCaptureSkill) { damage = 0; } if (CurrentHp <= damage) { SetDeathStatement(); } else { CurrentHp -= damage; } // only set the hit delay if we become the monsters target with this hit if (Target == -1) { LastSkill = DateTime.Now; } int nearestDistance = 100; foreach (KeyValuePair <long, long> kvp in DamageList) { ClientSession session = MapInstance.GetSessionByCharacterId(kvp.Key); if (session != null) { int distance = Map.GetDistance(new MapCell { X = MapX, Y = MapY }, new MapCell { X = session.Character.PositionX, Y = session.Character.PositionY }); if (distance < nearestDistance) { nearestDistance = distance; Target = session.Character.CharacterId; } } } switch (hitRequest.TargetHitType) { case TargetHitType.SingleTargetHit: if (!isCaptureSkill) { MapInstance?.Broadcast(StaticPacketHelper.SkillUsed(UserType.Player, hitRequest.Session.Character.CharacterId, 3, MapMonsterId, hitRequest.Skill.SkillVNum, hitRequest.Skill.Cooldown, hitRequest.Skill.AttackAnimation, hitRequest.SkillEffect, hitRequest.Session.Character.PositionX, hitRequest.Session.Character.PositionY, IsAlive, (int)((float)CurrentHp / (float)MaxHp * 100), damage, hitmode, (byte)(hitRequest.Skill.SkillType - 1))); } break; case TargetHitType.SingleTargetHitCombo: MapInstance?.Broadcast(StaticPacketHelper.SkillUsed(UserType.Player, hitRequest.Session.Character.CharacterId, 3, MapMonsterId, hitRequest.Skill.SkillVNum, hitRequest.Skill.Cooldown, hitRequest.SkillCombo.Animation, hitRequest.SkillCombo.Effect, hitRequest.Session.Character.PositionX, hitRequest.Session.Character.PositionY, IsAlive, (int)((float)CurrentHp / (float)MaxHp * 100), damage, hitmode, (byte)(hitRequest.Skill.SkillType - 1))); break; case TargetHitType.SingleAOETargetHit: switch (hitmode) { case 1: hitmode = 4; break; case 3: hitmode = 6; break; default: hitmode = 5; break; } if (hitRequest.ShowTargetHitAnimation) { MapInstance?.Broadcast(StaticPacketHelper.SkillUsed(UserType.Player, hitRequest.Session.Character.CharacterId, 3, MapMonsterId, hitRequest.Skill.SkillVNum, hitRequest.Skill.Cooldown, hitRequest.Skill.AttackAnimation, hitRequest.SkillEffect, hitRequest.Session.Character.PositionX, hitRequest.Session.Character.PositionY, IsAlive, (int)((float)CurrentHp / (float)MaxHp * 100), damage, hitmode, (byte)(hitRequest.Skill.SkillType - 1))); } else { MapInstance?.Broadcast(StaticPacketHelper.SkillUsed(UserType.Player, hitRequest.Session.Character.CharacterId, 3, MapMonsterId, 0, 0, 0, 0, 0, 0, IsAlive, (int)((float)CurrentHp / (float)MaxHp * 100), damage, hitmode, (byte)(hitRequest.Skill.SkillType - 1))); } break; case TargetHitType.AOETargetHit: switch (hitmode) { case 1: hitmode = 4; break; case 3: hitmode = 6; break; default: hitmode = 5; break; } MapInstance?.Broadcast(StaticPacketHelper.SkillUsed(UserType.Player, hitRequest.Session.Character.CharacterId, 3, MapMonsterId, hitRequest.Skill.SkillVNum, hitRequest.Skill.Cooldown, hitRequest.Skill.AttackAnimation, hitRequest.SkillEffect, hitRequest.Session.Character.PositionX, hitRequest.Session.Character.PositionY, IsAlive, (int)((float)CurrentHp / (float)MaxHp * 100), damage, hitmode, (byte)(hitRequest.Skill.SkillType - 1))); break; case TargetHitType.ZoneHit: MapInstance?.Broadcast(StaticPacketHelper.SkillUsed(UserType.Player, hitRequest.Session.Character.CharacterId, 3, MapMonsterId, hitRequest.Skill.SkillVNum, hitRequest.Skill.Cooldown, hitRequest.Skill.AttackAnimation, hitRequest.SkillEffect, hitRequest.MapX, hitRequest.MapY, IsAlive, (int)((float)CurrentHp / (float)MaxHp * 100), damage, 5, (byte)(hitRequest.Skill.SkillType - 1))); break; case TargetHitType.SpecialZoneHit: MapInstance?.Broadcast(StaticPacketHelper.SkillUsed(UserType.Player, hitRequest.Session.Character.CharacterId, 3, MapMonsterId, hitRequest.Skill.SkillVNum, hitRequest.Skill.Cooldown, hitRequest.Skill.AttackAnimation, hitRequest.SkillEffect, hitRequest.Session.Character.PositionX, hitRequest.Session.Character.PositionY, IsAlive, (int)((float)CurrentHp / (float)MaxHp * 100), damage, hitmode, (byte)(hitRequest.Skill.SkillType - 1))); break; } if (CurrentHp <= 0 && !isCaptureSkill) { // generate the kill bonus hitRequest.Session.Character.GenerateKillBonus(this); } } else { // monster already has been killed, send cancel hitRequest.Session.SendPacket(StaticPacketHelper.Cancel(2, MapMonsterId)); } if (IsBoss) { MapInstance.Broadcast(GenerateBoss()); } } // Respawn if (!IsAlive && ShouldRespawn != null && !ShouldRespawn.Value) { MapInstance.RemoveMonster(this); } if (!IsAlive && ShouldRespawn != null && ShouldRespawn.Value) { double timeDeath = (DateTime.Now - Death).TotalSeconds; if (timeDeath >= Monster.RespawnTime / 10d) { respawn(); } } // normal movement else if (Target == -1) { move(); } // target following else if (MapInstance != null) { GetNearestOponent(); HostilityTarget(); ClientSession targetSession = MapInstance.GetSessionByCharacterId(Target); // remove target in some situations if (targetSession == null || targetSession.Character.Invisible || targetSession.Character.Hp <= 0 || CurrentHp <= 0) { RemoveTarget(); return; } NpcMonsterSkill npcMonsterSkill = null; if (Skills != null && ServerManager.Instance.RandomNumber(0, 10) > 8) { npcMonsterSkill = Skills.Where(s => (DateTime.Now - s.LastSkillUse).TotalMilliseconds >= 100 * s.Skill?.Cooldown)?.OrderBy(rnd => _random.Next())?.FirstOrDefault(); } if (npcMonsterSkill?.Skill.TargetType == 1 && npcMonsterSkill?.Skill.HitType == 0) { targetHit(targetSession, npcMonsterSkill); } // check if target is in range if (!targetSession.Character.InvisibleGm && !targetSession.Character.Invisible && targetSession.Character.Hp > 0) { if (npcMonsterSkill != null && CurrentMp >= npcMonsterSkill.Skill.MpCost && Map.GetDistance(new MapCell { X = MapX, Y = MapY }, new MapCell { X = targetSession.Character.PositionX, Y = targetSession.Character.PositionY }) < npcMonsterSkill.Skill.Range) { targetHit(targetSession, npcMonsterSkill); } else if (Map.GetDistance(new MapCell { X = MapX, Y = MapY }, new MapCell { X = targetSession.Character.PositionX, Y = targetSession.Character.PositionY }) <= Monster.BasicRange) { targetHit(targetSession, npcMonsterSkill); } else { followTarget(targetSession); } } else { followTarget(targetSession); } } }
internal static void AttackMonster(this ClientSession session, Mate attacker, Skill skill, long targetId, short x, short y) { if (skill?.MpCost > attacker.Mp) { return; } attacker.LastSkillUse = DateTime.Now; attacker.Mp -= skill?.MpCost ?? 0; if (skill?.TargetType == 1 && skill.HitType == 1) { if (!session.HasCurrentMapInstance || skill.TargetRange == 0) { return; } //Probably some pvp stuff in here foreach (MapMonster mon in attacker.Owner.MapInstance.GetListMonsterInRange(attacker.PositionX, attacker.PositionY, skill.TargetRange).Where(s => s.CurrentHp > 0)) { mon.HitQueue.Enqueue(new HitRequest(TargetHitType.AoeTargetHit, session, attacker, skill)); session.CurrentMapInstance.Broadcast(StaticPacketHelper.CastOnTarget(UserType.Npc, attacker.MateTransportId, 2, mon.MapMonsterId, skill.CastAnimation, skill.CastEffect, skill.SkillVNum)); session.CurrentMapInstance.Broadcast(StaticPacketHelper.SkillUsed(UserType.Npc, attacker.MateTransportId, 3, mon.MapMonsterId, skill.SkillVNum, skill.Cooldown, skill.CastAnimation, skill.CastEffect, mon.MapX, mon.MapY, mon.CurrentHp > 0, (int)(mon.CurrentHp / (double)mon.MaxHp * 100), 0, 0, skill.SkillType)); } } else if (skill?.TargetType == 2 && skill.HitType == 0) { ClientSession target = attacker.Owner.Session ?? session; session.CurrentMapInstance.Broadcast(StaticPacketHelper.CastOnTarget(UserType.Npc, attacker.MateTransportId, 2, targetId, skill.CastAnimation, skill.CastEffect, skill.SkillVNum)); session.CurrentMapInstance.Broadcast(StaticPacketHelper.SkillUsed(UserType.Npc, attacker.MateTransportId, 3, targetId, skill.SkillVNum, skill.Cooldown, skill.CastAnimation, skill.CastEffect, x, y, true, 100, 0, 0, skill.SkillType)); skill.BCards.ToList().ForEach(s => { // Apply skill bcards to owner and pet s.ApplyBCards(target.Character); s.ApplyBCards(attacker); }); } else if (skill?.TargetType == 1 && skill.HitType != 1) { session.CurrentMapInstance.Broadcast(StaticPacketHelper.CastOnTarget(UserType.Npc, attacker.MateTransportId, 2, targetId, skill.CastAnimation, skill.CastEffect, skill.SkillVNum)); session.CurrentMapInstance.Broadcast(StaticPacketHelper.SkillUsed(UserType.Npc, attacker.MateTransportId, 3, targetId, skill.SkillVNum, skill.Cooldown, skill.CastAnimation, skill.CastEffect, x, y, true, 100, 0, 0, skill.SkillType)); switch (skill.HitType) { case 2: IEnumerable <MapMonster> entityInRange = session.Character.MapInstance?.GetListMonsterInRange(attacker.PositionX, attacker.PositionY, skill.TargetRange); foreach (BCard sb in skill.BCards) { if (sb.Type != (short)BCardType.CardType.Buff) { continue; } Buff bf = new Buff((short)sb.SecondData); if (bf.Card.BuffType != BuffType.Good) { continue; } var bonusBuff = 0; if (attacker.SpInstance != null && attacker.IsUsingSp && sb.BuffCard?.CardId >= 2000) { if (attacker.SpInstance.FirstPartnerSkill == skill.SkillVNum) { bonusBuff = (int)(attacker.SpInstance.FirstPartnerSkillRank - 1); } else if (attacker.SpInstance.SecondPartnerSkill == skill.SkillVNum) { bonusBuff = (int)(attacker.SpInstance.SecondPartnerSkillRank - 1); } else if (attacker.SpInstance.ThirdPartnerSkill == skill.SkillVNum) { bonusBuff = (int)(attacker.SpInstance.ThirdPartnerSkillRank - 1); } } sb.ApplyBCards(attacker, buffLevel: (short)bonusBuff); sb.ApplyBCards(attacker.Owner, buffLevel: (short)bonusBuff); } if (entityInRange != null) { foreach (var target in entityInRange) { foreach (BCard s in skill.BCards) { if (s.Type != (short)BCardType.CardType.Buff) { s.ApplyBCards(target, attacker); continue; } switch (attacker.Owner.MapInstance.MapInstanceType) { default: s.ApplyBCards(target); break; } } } } break; case 4: case 0: foreach (BCard bc in skill.BCards) { var bonusBuff = 0; if (attacker.SpInstance != null && attacker.IsUsingSp && bc.BuffCard?.CardId >= 2000) { if (attacker.SpInstance.FirstPartnerSkill == skill.SkillVNum) { bonusBuff = (int)(attacker.SpInstance.FirstPartnerSkillRank - 1); } else if (attacker.SpInstance.SecondPartnerSkill == skill.SkillVNum) { bonusBuff = (int)(attacker.SpInstance.SecondPartnerSkillRank - 1); } else if (attacker.SpInstance.ThirdPartnerSkill == skill.SkillVNum) { bonusBuff = (int)(attacker.SpInstance.ThirdPartnerSkillRank - 1); } } if (bc.Type == (short)BCardType.CardType.Buff && bc.BuffCard?.BuffType == BuffType.Good) { bc.ApplyBCards(attacker, buffLevel: (short)bonusBuff); bc.ApplyBCards(attacker.Owner, buffLevel: (short)bonusBuff); } else { bc.ApplyBCards(attacker); } } break; } } else if (skill != null && skill.TargetType == 0 && session.HasCurrentMapInstance) { MapMonster monsterToAttack = attacker.Owner.MapInstance.GetMonster(targetId); if (monsterToAttack == null || attacker.Mp <= skill.MpCost) { return; } if (Map.GetDistance(new MapCell { X = monsterToAttack.MapX, Y = monsterToAttack.MapY }, new MapCell { X = monsterToAttack.MapX, Y = monsterToAttack.MapY }) >= skill.Range + 1 + monsterToAttack.Monster.BasicArea) { return; } foreach (BCard bc in skill.BCards) { var bf = new Buff((short)bc.SecondData); if (bf.Card?.BuffType == BuffType.Bad || bf.Card?.BuffType == BuffType.Neutral) { bc.ApplyBCards(monsterToAttack, attacker); } } session.SendPacket(attacker.GenerateStatInfo()); if (skill.HitType == 3) { monsterToAttack.HitQueue.Enqueue(new HitRequest(TargetHitType.SingleAoeTargetHit, session, attacker, skill)); } else { if (skill.TargetRange != 0) { IEnumerable <MapMonster> monstersInAorRange = attacker.Owner.MapInstance?.GetListMonsterInRange(monsterToAttack.MapX, monsterToAttack.MapY, skill.TargetRange); monsterToAttack.HitQueue.Enqueue(new HitRequest(TargetHitType.SingleAoeTargetHit, session, attacker, skill)); if (monstersInAorRange != null) { foreach (MapMonster mon in monstersInAorRange) { mon.HitQueue.Enqueue(new HitRequest(TargetHitType.SingleAoeTargetHit, session, attacker, skill)); } } } else { if (!monsterToAttack.IsAlive) { session.SendPacket("cancel 2 0"); return; } monsterToAttack.HitQueue.Enqueue(new HitRequest(TargetHitType.SingleAoeTargetHit, session, attacker, skill)); } } } }
internal static void AttackCharacter(this ClientSession session, Mate attacker, NpcMonsterSkill skill, Character target) { if (attacker == null || target == null) { return; } if (target.Hp > 0 && attacker.Hp > 0) { if ((session.CurrentMapInstance.MapInstanceId == ServerManager.Instance.ArenaInstance.MapInstanceId || session.CurrentMapInstance.MapInstanceId == ServerManager.Instance.FamilyArenaInstance.MapInstanceId) && (session.CurrentMapInstance.Map.JaggedGrid[session.Character.PositionX][ session.Character.PositionY]?.Value != 0 || target.Session.CurrentMapInstance.Map.JaggedGrid[target.PositionX][ target.PositionY] ?.Value != 0)) { // User in SafeZone session.SendPacket(StaticPacketHelper.Cancel(2, target.CharacterId)); return; } if (target.IsSitting) { target.Rest(); } short castAnimation = -1; short castEffect = -1; short skillVnum = 0; short cooldown = 0; byte type = 0; if (skill != null) { castAnimation = skill.Skill.CastAnimation; castEffect = skill.Skill.CastEffect; skillVnum = skill.SkillVNum; cooldown = skill.Skill.Cooldown; type = skill.Skill.Type; } var hitmode = 0; var onyxWings = false; BattleEntity battleEntity = new BattleEntity(attacker); BattleEntity battleEntityDefense = new BattleEntity(target); session.CurrentMapInstance?.Broadcast(StaticPacketHelper.CastOnTarget(UserType.Npc, attacker.MateTransportId, 3, target.CharacterId, castAnimation, castEffect, skillVnum)); session.CurrentMapInstance?.Broadcast(StaticPacketHelper.SkillUsed(UserType.Npc, attacker.MateTransportId, 3, target.CharacterId, skillVnum, cooldown, castAnimation, castEffect, target.MapX, target.MapY, target.Hp > 0, (int)(target.Hp / (double)target.HPMax * 100), 0, 0, type)); var damage = DamageHelper.Instance.CalculateDamage(battleEntity, battleEntityDefense, skill?.Skill, ref hitmode, ref onyxWings); if (target.HasGodMode) { damage = 0; hitmode = 1; } else if (target.LastPvpRevive > DateTime.Now.AddSeconds(-10) || session.Character.LastPvpRevive > DateTime.Now.AddSeconds(-10)) { damage = 0; hitmode = 1; } int[] manaShield = target.GetBuff(BCardType.CardType.LightAndShadow, (byte)AdditionalTypes.LightAndShadow.InflictDamageToMP); if (manaShield[0] != 0 && hitmode != 1) { var reduce = damage / 100 * manaShield[0]; if (target.Mp < reduce) { target.Mp = 0; } else { target.Mp -= reduce; } } target.GetDamage(damage / 2); target.LastDefence = DateTime.Now; target.Session.SendPacket(target.GenerateStat()); var isAlive = target.Hp > 0; if (!isAlive && target.Session.HasCurrentMapInstance) { if (target.Session.CurrentMapInstance.Map?.MapTypes.Any( s => s.MapTypeId == (short)MapTypeEnum.Act4) == true) { if (ServerManager.Instance.ChannelId == 51 && ServerManager.Instance.Act4DemonStat.Mode == 0 && ServerManager.Instance.Act4AngelStat.Mode == 0) { switch (session.Character.Faction) { case FactionType.Angel: ServerManager.Instance.Act4AngelStat.Percentage += 100; break; case FactionType.Demon: ServerManager.Instance.Act4DemonStat.Percentage += 100; break; } } session.Character.Act4Kill++; target.Act4Dead++; target.GetAct4Points(-1); if (target.Level + 10 >= session.Character.Level && session.Character.Level <= target.Level - 10) { session.Character.GetAct4Points(2); } if (target.Reputation < 50000) { target.Session.SendPacket(session.Character.GenerateSay( string.Format(Language.Instance.GetMessageFromKey("LOSE_REP"), 0), 11)); } else { target.Reputation -= target.Level * 50; session.Character.Reputation += target.Level * 50; session.SendPacket(session.Character.GenerateLev()); target.Session.SendPacket(target.GenerateSay( string.Format(Language.Instance.GetMessageFromKey("LOSE_REP"), (short)(target.Level * 50)), 11)); } foreach (ClientSession sess in ServerManager.Instance.Sessions.Where( s => s.HasSelectedCharacter)) { if (sess.Character.Faction == session.Character.Faction) { sess.SendPacket(sess.Character.GenerateSay( string.Format( Language.Instance.GetMessageFromKey( $"ACT4_PVP_KILL{(int)target.Faction}"), session.Character.Name), 12)); } else if (sess.Character.Faction == target.Faction) { sess.SendPacket(sess.Character.GenerateSay( string.Format( Language.Instance.GetMessageFromKey( $"ACT4_PVP_DEATH{(int)target.Faction}"), target.Name), 11)); } } target.Session.SendPacket(target.GenerateFd()); target.DisableBuffs(BuffType.All, force: true); target.Session.CurrentMapInstance.Broadcast(target.Session, target.GenerateIn(), ReceiverType.AllExceptMe); target.Session.CurrentMapInstance.Broadcast(target.Session, target.GenerateGidx(), ReceiverType.AllExceptMe); target.Session.SendPacket( target.GenerateSay(Language.Instance.GetMessageFromKey("ACT4_PVP_DIE"), 11)); target.Session.SendPacket( UserInterfaceHelper.GenerateMsg(Language.Instance.GetMessageFromKey("ACT4_PVP_DIE"), 0)); Observable.Timer(TimeSpan.FromMilliseconds(2000)).Subscribe(o => { target.Session.CurrentMapInstance?.Broadcast(target.Session, $"c_mode 1 {target.CharacterId} 1564 0 0 0"); target.Session.CurrentMapInstance?.Broadcast(target.GenerateRevive()); }); Observable.Timer(TimeSpan.FromMilliseconds(30000)).Subscribe(o => { target.Hp = (int)target.HPLoad(); target.Mp = (int)target.MPLoad(); var x = (short)(39 + ServerManager.RandomNumber <short>(-2, 3)); var y = (short)(42 + ServerManager.RandomNumber <short>(-2, 3)); switch (target.Faction) { case FactionType.Angel: ServerManager.Instance.ChangeMap(target.CharacterId, 130, x, y); break; case FactionType.Demon: ServerManager.Instance.ChangeMap(target.CharacterId, 131, x, y); break; default: { target.MapId = 145; target.MapX = 51; target.MapY = 41; var connection = CommunicationServiceClient.Instance.RetrieveOriginWorld(session.Account.AccountId); if (string.IsNullOrWhiteSpace(connection)) { return; } var port = Convert.ToInt32(connection.Split(':')[1]); session.Character.ChangeChannel(connection.Split(':')[0], port, 3); return; } } target.Session.CurrentMapInstance?.Broadcast(target.Session, target.GenerateTp()); target.Session.CurrentMapInstance?.Broadcast(target.GenerateRevive()); target.Session.SendPacket(target.GenerateStat()); }); } } if (hitmode != 1) { skill?.Skill?.BCards.Where(s => s.Type.Equals((byte)BCardType.CardType.Buff)).ToList() .ForEach(s => s.ApplyBCards(target, session.Character)); } session.CurrentMapInstance?.Broadcast(StaticPacketHelper.SkillUsed(UserType.Npc, attacker.MateTransportId, 1, target.CharacterId, 0, 12, 11, 200, 0, 0, isAlive, (int)(target.Hp / target.HPLoad() * 100), damage, hitmode, 0)); } else { // monster already has been killed, send cancel session.SendPacket(StaticPacketHelper.Cancel(2, target.CharacterId)); } }
internal static void AttackCharacter(this ClientSession session, Mate attacker, Skill skil, Character target) { if (attacker == null || target == null) { return; } if (skil == null) { skil = ServerManager.GetSkill(200); } if (target.Hp > 0 && attacker.IsAlive) { if ((session.CurrentMapInstance.MapInstanceId == ServerManager.Instance.ArenaInstance.MapInstanceId || session.CurrentMapInstance.MapInstanceId == ServerManager.Instance.FamilyArenaInstance.MapInstanceId) && (session.CurrentMapInstance.Map.JaggedGrid[session.Character.PositionX][ session.Character.PositionY]?.Value != 0 || target.Session.CurrentMapInstance.Map.JaggedGrid[target.PositionX][ target.PositionY] ?.Value != 0)) { // User in SafeZone session.SendPacket(StaticPacketHelper.Cancel(2, target.CharacterId)); return; } if (target.IsSitting) { target.Rest(); } int hitmode = 0; bool onyxWings = false; attacker.LastSkillUse = DateTime.UtcNow; BattleEntity battleEntity = new BattleEntity(attacker); BattleEntity battleEntityDefense = new BattleEntity(target, null); session.CurrentMapInstance?.Broadcast(StaticPacketHelper.CastOnTarget(UserType.Npc, attacker.MateTransportId, 1, target.CharacterId, skil.CastAnimation, skil.CastEffect, skil.SkillVNum)); int damage = DamageHelper.Instance.CalculateDamage(battleEntity, battleEntityDefense, skil, ref hitmode, ref onyxWings); if (target.HasGodMode) { damage = 0; hitmode = 1; } else if (target.LastPvpRevive > DateTime.UtcNow.AddSeconds(-10) || session.Character.LastPvpRevive > DateTime.UtcNow.AddSeconds(-10)) { damage = 0; hitmode = 1; } int[] manaShield = target.GetBuff(BCardType.CardType.LightAndShadow, (byte)AdditionalTypes.LightAndShadow.InflictDamageToMP); if (manaShield[0] != 0 && hitmode != 1) { int reduce = damage / 100 * manaShield[0]; if (target.Mp < reduce) { target.Mp = 0; } else { target.Mp -= reduce; } } target.GetDamage(damage / 2); target.LastDefence = DateTime.UtcNow; target.Session.SendPacket(target.GenerateStat()); bool isAlive = target.Hp > 0; if (!isAlive && target.Session.HasCurrentMapInstance) { if (target.Session.CurrentMapInstance.Map?.MapTypes.Any( s => s.MapTypeId == (short)MapTypeEnum.Act4) == true) { if (ServerManager.Instance.ChannelId == 51 && ServerManager.Instance.Act4DemonStat.Mode == 0 && ServerManager.Instance.Act4AngelStat.Mode == 0) { switch (session.Character.Faction) { case FactionType.Angel: ServerManager.Instance.Act4AngelStat.Percentage += 500; break; case FactionType.Demon: ServerManager.Instance.Act4DemonStat.Percentage += 500; break; } } session.Character.Act4Kill++; target.Act4Dead++; target.GetAct4Points(-1); if (target.Level + 20 >= session.Character.Level && session.Character.Level <= target.Level - 20) { session.Character.GetAct4Points(2); } if (target.Reputation < 9999999999) { target.Session.SendPacket(session.Character.GenerateSay( string.Format(Language.Instance.GetMessageFromKey("LOSE_REP"), 0), 11)); } else { target.Reputation -= target.Level * 0; session.Character.Reputation += target.Level * 150; session.SendPacket(session.Character.GenerateLev()); target.Session.SendPacket(target.GenerateSay( string.Format(Language.Instance.GetMessageFromKey("LOSE_REP"), (short)(target.Level * 0)), 11)); } foreach (ClientSession sess in ServerManager.Instance.Sessions.Where( s => s.HasSelectedCharacter)) { if (sess.Character.Faction == session.Character.Faction) { sess.SendPacket(sess.Character.GenerateSay( string.Format( Language.Instance.GetMessageFromKey( $"ACT4_PVP_KILL{(int)target.Faction}"), session.Character.Name), 12)); } else if (sess.Character.Faction == target.Faction) { sess.SendPacket(sess.Character.GenerateSay( string.Format( Language.Instance.GetMessageFromKey( $"ACT4_PVP_DEATH{(int)target.Faction}"), target.Name), 11)); } } target.Session.SendPacket(target.GenerateFd()); target.DisableBuffs(BuffType.All, force: true); target.Session.CurrentMapInstance.Broadcast(target.Session, target.GenerateIn(), ReceiverType.AllExceptMe); target.Session.CurrentMapInstance.Broadcast(target.Session, target.GenerateGidx(), ReceiverType.AllExceptMe); target.Session.SendPacket( target.GenerateSay(Language.Instance.GetMessageFromKey("ACT4_PVP_DIE"), 11)); target.Session.SendPacket( UserInterfaceHelper.GenerateMsg(Language.Instance.GetMessageFromKey("ACT4_PVP_DIE"), 0)); if (target.MapInstanceId == CaligorRaid.CaligorMapInstance?.MapInstanceId) { target.Hp = (int)target.HPLoad(); target.Mp = (int)target.MPLoad(); if (target.Faction == FactionType.Angel) { ServerManager.Instance.ChangeMapInstance(target.CharacterId, CaligorRaid.CaligorMapInstance.MapInstanceId, 70, 159); } else if (target.Faction == FactionType.Demon) { ServerManager.Instance.ChangeMapInstance(target.CharacterId, CaligorRaid.CaligorMapInstance.MapInstanceId, 110, 159); } target.Session.CurrentMapInstance?.Broadcast(target.Session, target.GenerateTp()); target.Session.CurrentMapInstance?.Broadcast(target.GenerateRevive()); target.Session.SendPacket(target.GenerateStat()); return; } Observable.Timer(TimeSpan.FromMilliseconds(2000)).Subscribe(o => { target.Session.CurrentMapInstance?.Broadcast(target.Session, $"c_mode 1 {target.CharacterId} 1564 0 0 0"); target.Session.CurrentMapInstance?.Broadcast(target.GenerateRevive()); }); Observable.Timer(TimeSpan.FromMilliseconds(30000)).Subscribe(o => { target.Hp = (int)target.HPLoad(); target.Mp = (int)target.MPLoad(); short x = (short)(39 + ServerManager.RandomNumber(-2, 3)); short y = (short)(42 + ServerManager.RandomNumber(-2, 3)); if (target.Faction == FactionType.Angel) { ServerManager.Instance.ChangeMap(target.CharacterId, 130, x, y); } else if (target.Faction == FactionType.Demon) { ServerManager.Instance.ChangeMap(target.CharacterId, 131, x, y); } else { target.MapId = 145; target.MapX = 51; target.MapY = 41; string connection = CommunicationServiceClient.Instance.RetrieveOriginWorld(session.Account.AccountId); if (string.IsNullOrWhiteSpace(connection)) { return; } int port = Convert.ToInt32(connection.Split(':')[1]); session.Character.ChangeChannel(connection.Split(':')[0], port, 3); return; } target.Session.CurrentMapInstance?.Broadcast(target.Session, target.GenerateTp()); target.Session.CurrentMapInstance?.Broadcast(target.GenerateRevive()); target.Session.SendPacket(target.GenerateStat()); }); } else { session.Character.TalentWin++; target.TalentLose++; session.CurrentMapInstance?.Broadcast(session.Character.GenerateSay( string.Format(Language.Instance.GetMessageFromKey("PVP_KILL"), session.Character.Name, target.Name), 10)); Observable.Timer(TimeSpan.FromMilliseconds(1000)).Subscribe(o => ServerManager.Instance.AskPvpRevive(target.CharacterId)); } } if (hitmode != 1) { skil.BCards.Where(s => s.Type.Equals((byte)BCardType.CardType.Buff)).ToList() .ForEach(s => s.ApplyBCards(target, session.Character)); } session.SendPacket(StaticPacketHelper.GenerateEff(UserType.Npc, attacker.MateTransportId, 5005)); Observable.Timer(TimeSpan.FromMilliseconds(skil.CastTime)).Subscribe(o => { session.CurrentMapInstance?.Broadcast(StaticPacketHelper.SkillUsed(UserType.Npc, attacker.MateTransportId, 1, target.CharacterId, skil.SkillVNum, skil.Cooldown, skil.AttackAnimation, skil.Effect, 0, 0, target.Hp > 0, (int)(target.Hp / (float)target.HPLoad() * 100), damage, hitmode, 0)); }); // switch (hitRequest.TargetHitType) { case TargetHitType.SingleTargetHit: // hitRequest.Session.CurrentMapInstance?.Broadcast(StaticPacketHelper.SkillUsed(UserType.Player, // hitRequest.Session.Character.CharacterId, 1, target.Character.CharacterId, // hitRequest.Skill.SkillVNum, hitRequest.Skill.Cooldown, // hitRequest.Skill.AttackAnimation, hitRequest.SkillEffect, // hitRequest.Session.Character.PositionX, hitRequest.Session.Character.PositionY, // isAlive, (int) (target.Character.Hp / (float) target.Character.HPLoad() * 100), // damage, hitmode, (byte) (hitRequest.Skill.SkillType - 1))); break; // // case TargetHitType.SingleTargetHitCombo: // hitRequest.Session.CurrentMapInstance?.Broadcast(StaticPacketHelper.SkillUsed(UserType.Player, // hitRequest.Session.Character.CharacterId, 1, target.Character.CharacterId, // hitRequest.Skill.SkillVNum, hitRequest.Skill.Cooldown, // hitRequest.SkillCombo.Animation, hitRequest.SkillCombo.Effect, // hitRequest.Session.Character.PositionX, hitRequest.Session.Character.PositionY, // isAlive, (int) (target.Character.Hp / (float) target.Character.HPLoad() * 100), // damage, hitmode, (byte) (hitRequest.Skill.SkillType - 1))); break; // // case TargetHitType.SingleAOETargetHit: switch (hitmode) { case 1: hitmode = 4; break; // // case 3: hitmode = 6; break; // // default: hitmode = 5; break; } // // if (hitRequest.ShowTargetHitAnimation) { // hitRequest.Session.CurrentMapInstance?.Broadcast(StaticPacketHelper.SkillUsed( // UserType.Player, hitRequest.Session.Character.CharacterId, 1, // target.Character.CharacterId, hitRequest.Skill.SkillVNum, // hitRequest.Skill.Cooldown, hitRequest.Skill.AttackAnimation, // hitRequest.SkillEffect, 0, 0, isAlive, (int) (target.Character.Hp / (float) // target.Character.HPLoad() * 100), 0, 0, (byte) (hitRequest.Skill.SkillType - 1))); } // // hitRequest.Session.CurrentMapInstance?.Broadcast(StaticPacketHelper.SkillUsed(UserType.Player, // hitRequest.Session.Character.CharacterId, 1, target.Character.CharacterId, // hitRequest.Skill.SkillVNum, hitRequest.Skill.Cooldown, // hitRequest.Skill.AttackAnimation, hitRequest.SkillEffect, // hitRequest.Session.Character.PositionX, hitRequest.Session.Character.PositionY, // isAlive, (int) (target.Character.Hp / (float) target.Character.HPLoad() * 100), // damage, hitmode, (byte) (hitRequest.Skill.SkillType - 1))); break; // // case TargetHitType.AOETargetHit: switch (hitmode) { case 1: hitmode = 4; break; // // case 3: hitmode = 6; break; // // default: hitmode = 5; break; } // // hitRequest.Session.CurrentMapInstance?.Broadcast(StaticPacketHelper.SkillUsed(UserType.Player, // hitRequest.Session.Character.CharacterId, 1, target.Character.CharacterId, // hitRequest.Skill.SkillVNum, hitRequest.Skill.Cooldown, // hitRequest.Skill.AttackAnimation, hitRequest.SkillEffect, // hitRequest.Session.Character.PositionX, hitRequest.Session.Character.PositionY, // isAlive, (int) (target.Character.Hp / (float) target.Character.HPLoad() * 100), // damage, hitmode, (byte) (hitRequest.Skill.SkillType - 1))); break; // // case TargetHitType.ZoneHit: // hitRequest.Session.CurrentMapInstance?.Broadcast(StaticPacketHelper.SkillUsed(UserType.Player, // hitRequest.Session.Character.CharacterId, 1, target.Character.CharacterId, // hitRequest.Skill.SkillVNum, hitRequest.Skill.Cooldown, // hitRequest.Skill.AttackAnimation, hitRequest.SkillEffect, hitRequest.MapX, // hitRequest.MapY, isAlive, (int) (target.Character.Hp / (float) // target.Character.HPLoad() * 100), damage, 5, (byte) (hitRequest.Skill.SkillType - // 1))); break; // // case TargetHitType.SpecialZoneHit: // hitRequest.Session.CurrentMapInstance?.Broadcast(StaticPacketHelper.SkillUsed(UserType.Player, // hitRequest.Session.Character.CharacterId, 1, target.Character.CharacterId, // hitRequest.Skill.SkillVNum, hitRequest.Skill.Cooldown, // hitRequest.Skill.AttackAnimation, hitRequest.SkillEffect, // hitRequest.Session.Character.PositionX, hitRequest.Session.Character.PositionY, // isAlive, (int) (target.Character.Hp / target.Character.HPLoad() * 100), damage, 0, // (byte) (hitRequest.Skill.SkillType - 1))); break; // // default: Logger.Warn("Not Implemented TargetHitType Handling!"); break; } } else { // player already has been killed, send cancel session.SendPacket(StaticPacketHelper.Cancel(2, target.CharacterId)); } }
public void ApplyBCards(object session, object sender = null) { //Console.WriteLine($"BCardId: {BCardId} Type: {(BCardType.CardType)Type} SubType: {SubType} CardId: {CardId?.ToString() ?? "null"} ItemVNum: {ItemVNum?.ToString() ?? "null"} SkillVNum: {SkillVNum?.ToString() ?? "null"} SessionType: {session?.GetType().ToString() ?? "null"} SenderType: {sender?.GetType().ToString() ?? "null"}"); switch ((BCardType.CardType)Type) { case BCardType.CardType.Buff: { if (ServerManager.RandomNumber() < FirstData) { Character senderCharacter = sender is ClientSession senderSession ? senderSession.Character : sender as Character; if (session is Character character) { short cardId = (short)SecondData; // If either Berserk Spirit or Strong Berserk Spirit is active // then don't add Weak Berserk Spirit if (cardId == 601 && character.Buff?.Any(s => s?.Card?.CardId == 602 || s?.Card?.CardId == 603) == true) { break; } if (senderCharacter != null) { // TODO: Get anti stats from BCard character.AddBuff(new Buff((short)SecondData, senderCharacter.Level, senderCharacter)); } else { character.AddBuff(new Buff((short)SecondData, character.Level)); } } else if (session is MapMonster mapMonster) { if (senderCharacter != null) { mapMonster.AddBuff(new Buff((short)SecondData, senderCharacter.Level, senderCharacter)); } else { mapMonster.AddBuff(new Buff((short)SecondData, mapMonster.Monster.Level)); } } } } break; case BCardType.CardType.Move: { if (session is Character character) { character.LastSpeedChange = DateTime.Now; character.Session.SendPacket(character.GenerateCond()); } } break; case BCardType.CardType.Summons: { if (session is Character character) { if (character.MapInstance != null) { List <MonsterToSummon> monsterList = new List <MonsterToSummon>(); if (SubType == (byte)AdditionalTypes.Summons.Summons / 10) { int aliveTime = ServerManager.GetNpc((short)SecondData).RespawnTime; for (int i = 0; i < FirstData; i++) { MapCell mapCell = new MapCell { X = (short)(ServerManager.RandomNumber(-1, 2) + character.PositionX), Y = (short)(ServerManager.RandomNumber(-1, 2) + character.PositionY), }; monsterList.Add(new MonsterToSummon((short)SecondData, mapCell, -1, true, false, false, true, false, -1, character, aliveTime, false)); } } if (monsterList.Any()) { EventHelper.Instance.RunEvent(new EventContainer(character.MapInstance, EventActionType.SPAWNMONSTERS, monsterList)); } } } } break; case BCardType.CardType.SpecialAttack: break; case BCardType.CardType.SpecialDefence: break; case BCardType.CardType.AttackPower: break; case BCardType.CardType.Target: break; case BCardType.CardType.Critical: break; case BCardType.CardType.SpecialCritical: break; case BCardType.CardType.Element: break; case BCardType.CardType.IncreaseDamage: break; case BCardType.CardType.Defence: break; case BCardType.CardType.DodgeAndDefencePercent: break; case BCardType.CardType.Block: break; case BCardType.CardType.Absorption: break; case BCardType.CardType.ElementResistance: break; case BCardType.CardType.EnemyElementResistance: break; case BCardType.CardType.Damage: break; case BCardType.CardType.GuarantedDodgeRangedAttack: break; case BCardType.CardType.Morale: break; case BCardType.CardType.Casting: break; case BCardType.CardType.Reflection: break; case BCardType.CardType.DrainAndSteal: break; case BCardType.CardType.HealingBurningAndCasting: { Character senderCharacter = sender is ClientSession senderSession ? senderSession.Character : sender as Character; if (senderCharacter != null) { #region Character if (session is Character character) { void HealingBurningAndCastingAction() { if (!character.IsAlive || character.MapInstance == null || character.Session == null) { return; } int amount = 0; if (SubType == (byte)AdditionalTypes.HealingBurningAndCasting.RestoreHP / 10 || SubType == (byte)AdditionalTypes.HealingBurningAndCasting.DecreaseHP / 10) { if (FirstData > 0) { if (IsLevelScaled) { amount = senderCharacter.Level * FirstData; } else { amount = FirstData; } if (character.Hp + amount > character.HPMax) { amount = character.HPMax - character.Hp; } character.Hp += amount; character.MapInstance.Broadcast(character.GenerateRc(amount)); } else { if (IsLevelScaled) { amount = senderCharacter.Level * (FirstData - 1); } else { amount = FirstData; } amount *= -1; if (character.Hp - amount < 1) { amount = character.Hp - 1; } character.GetDamage(amount); character.MapInstance.Broadcast(character.GenerateDm(amount)); } character.Session.SendPacket(character.GenerateStat()); } else if (SubType == (byte)AdditionalTypes.HealingBurningAndCasting.RestoreMP / 10 || SubType == (byte)AdditionalTypes.HealingBurningAndCasting.DecreaseMP / 10) { if (FirstData > 0) { if (IsLevelScaled) { amount = senderCharacter.Level * FirstData; } else { amount = FirstData; } if (character.Mp + amount > character.MPMax) { amount = character.MPMax - character.Mp; } character.Mp += amount; } else { if (IsLevelScaled) { amount = senderCharacter.Level * (FirstData - 1); } else { amount = FirstData; } amount *= -1; if (character.Mp - amount < 1) { amount = character.Mp - 1; } character.DecreaseMp(amount); } character.Session.SendPacket(character.GenerateStat()); } } HealingBurningAndCastingAction(); if (ThirdData > 0 && CardId != null) { IDisposable disposable = Observable.Interval(TimeSpan.FromSeconds(ThirdData * 2)) .Subscribe(s => HealingBurningAndCastingAction()); character.DisposeBCard(BCardId); character.BCardDisposables[BCardId] = disposable; } } #endregion #region MapMonster else if (session is MapMonster mapMonster) { void HealingBurningAndCastingAction() { if (!mapMonster.IsAlive || mapMonster.MapInstance == null) { return; } int amount = 0; if (SubType == (byte)AdditionalTypes.HealingBurningAndCasting.RestoreHP / 10 || SubType == (byte)AdditionalTypes.HealingBurningAndCasting.DecreaseHP / 10) { if (FirstData > 0) { if (IsLevelScaled) { amount = senderCharacter.Level * FirstData; } else { amount = FirstData; } if (mapMonster.CurrentHp + amount > mapMonster.MaxHp) { amount = mapMonster.MaxHp - mapMonster.CurrentHp; } mapMonster.CurrentHp += amount; mapMonster.MapInstance.Broadcast(mapMonster.GenerateRc(amount)); } else { if (IsLevelScaled) { amount = senderCharacter.Level * (FirstData - 1); } else { amount = FirstData; } amount *= -1; if (mapMonster.CurrentHp - amount < 1) { amount = mapMonster.CurrentHp - 1; } mapMonster.CurrentHp -= amount; mapMonster.MapInstance.Broadcast(mapMonster.GenerateDm(amount)); } } if (SubType == (byte)AdditionalTypes.HealingBurningAndCasting.RestoreMP / 10 || SubType == (byte)AdditionalTypes.HealingBurningAndCasting.DecreaseMP / 10) { if (FirstData > 0) { if (IsLevelScaled) { amount = senderCharacter.Level * FirstData; } else { amount = FirstData; } if (mapMonster.CurrentMp + amount > mapMonster.MaxMp) { amount = mapMonster.MaxMp - mapMonster.CurrentMp; } mapMonster.CurrentMp += amount; } else { if (IsLevelScaled) { amount = senderCharacter.Level * (FirstData - 1); } else { amount = FirstData; } amount *= -1; if (mapMonster.CurrentMp - amount < 1) { amount = mapMonster.CurrentMp - 1; } mapMonster.CurrentMp -= amount; } } } HealingBurningAndCastingAction(); if (ThirdData > 0 && CardId != null) { IDisposable disposable = Observable.Interval(TimeSpan.FromSeconds(ThirdData * 2)) .Subscribe(s => HealingBurningAndCastingAction()); mapMonster.DisposeBCard(BCardId); mapMonster.BCardDisposables[BCardId] = disposable; } } #endregion } } break; case BCardType.CardType.HPMP: { if (SubType == (byte)AdditionalTypes.HPMP.DecreaseRemainingMP / 10) { if (FirstData < 0) { double multiplier = (FirstData * -1) / 100D; if (session is Character character) { character.DecreaseMp((int)(character.Mp * multiplier)); character.Session?.SendPacket(character.GenerateStat()); } else if (session is MapMonster mapMonster) { mapMonster.DecreaseMp((int)(mapMonster.CurrentMp * multiplier)); } } } } break; case BCardType.CardType.SpecializationBuffResistance: { if (SubType == (byte)AdditionalTypes.SpecializationBuffResistance.RemoveGoodEffects / 10) { if (session is Character character) { if (FirstData < 0) { if (ServerManager.RandomNumber() < (FirstData * -1)) { character.Buff?.GetAllItems()?.Where(s => s?.Card?.BuffType == BuffType.Bad && s.Card.Level < SecondData)? .ToList()?.ForEach(s => character.RemoveBuff(s.Card.CardId)); } } else { if (ServerManager.RandomNumber() < FirstData) { character.Buff?.GetAllItems()?.Where(s => s?.Card?.BuffType == BuffType.Good && s.Card.Level < SecondData)? .ToList()?.ForEach(s => character.RemoveBuff(s.Card.CardId)); } } } } } break; case BCardType.CardType.SpecialEffects: { if (SubType == (byte)AdditionalTypes.SpecialEffects.ShadowAppears / 10) { if (session is Character character) { character.NumberOfShadows = FirstData; character.ShadowsDistance = SecondData; character.MapInstance?.Broadcast(character.GenerateSpeed()); } } } break; case BCardType.CardType.Capture: { if (session is MapMonster mapMonster && sender is ClientSession senderSession) { NpcMonster mateNpc = ServerManager.GetNpc(mapMonster.MonsterVNum); if (mateNpc != null) { if (mapMonster.Monster.Catch) { if (mapMonster.IsAlive && mapMonster.CurrentHp <= (int)((double)mapMonster.MaxHp / 2)) { if (mapMonster.Monster.Level < senderSession.Character.Level) { // TODO: Find a new algorithm int[] chance = { 100, 80, 60, 40, 20, 0 }; if (ServerManager.RandomNumber() < chance[ServerManager.RandomNumber(0, 5)]) { Mate mate = new Mate(senderSession.Character, mateNpc, (byte)(mapMonster.Monster.Level - 15 > 0 ? mapMonster.Monster.Level - 15 : 1), MateType.Pet); if (senderSession.Character.CanAddMate(mate)) { senderSession.Character.AddPetWithSkill(mate); senderSession.SendPacket(UserInterfaceHelper.GenerateMsg(Language.Instance.GetMessageFromKey("CATCH_SUCCESS"), 0)); senderSession.CurrentMapInstance?.Broadcast(StaticPacketHelper.GenerateEff(UserType.Player, senderSession.Character.CharacterId, 197)); senderSession.CurrentMapInstance?.Broadcast(StaticPacketHelper.SkillUsed(UserType.Player, senderSession.Character.CharacterId, 3, mapMonster.MapMonsterId, -1, 0, 15, -1, -1, -1, true, (int)((float)mapMonster.CurrentHp / (float)mapMonster.MaxHp * 100), 0, -1, 0)); mapMonster.SetDeathStatement(); senderSession.CurrentMapInstance?.Broadcast(StaticPacketHelper.Out(UserType.Monster, mapMonster.MapMonsterId)); } else { senderSession.SendPacket(senderSession.Character.GenerateSay(Language.Instance.GetMessageFromKey("PET_SLOT_FULL"), 10)); senderSession.SendPacket(StaticPacketHelper.Cancel(2, mapMonster.MapMonsterId)); } } else { senderSession.SendPacket(UserInterfaceHelper.GenerateMsg(Language.Instance.GetMessageFromKey("CATCH_FAIL"), 0)); senderSession.CurrentMapInstance?.Broadcast(StaticPacketHelper.SkillUsed(UserType.Player, senderSession.Character.CharacterId, 3, mapMonster.MapMonsterId, -1, 0, 15, -1, -1, -1, true, (int)((float)mapMonster.CurrentHp / (float)mapMonster.MaxHp * 100), 0, -1, 0)); } } else { senderSession.SendPacket(UserInterfaceHelper.GenerateMsg(Language.Instance.GetMessageFromKey("LEVEL_LOWER_THAN_MONSTER"), 0)); senderSession.SendPacket(StaticPacketHelper.Cancel(2, mapMonster.MapMonsterId)); } } else { senderSession.SendPacket(UserInterfaceHelper.GenerateMsg(Language.Instance.GetMessageFromKey("CURRENT_HP_TOO_HIGH"), 0)); senderSession.SendPacket(StaticPacketHelper.Cancel(2, mapMonster.MapMonsterId)); } } else { senderSession.SendPacket(UserInterfaceHelper.GenerateMsg(Language.Instance.GetMessageFromKey("MONSTER_CANT_BE_CAPTURED"), 0)); senderSession.SendPacket(StaticPacketHelper.Cancel(2, mapMonster.MapMonsterId)); } } } } break; case BCardType.CardType.SpecialDamageAndExplosions: break; case BCardType.CardType.SpecialEffects2: { if (SubType == (byte)AdditionalTypes.SpecialEffects2.TeleportInRadius / 10) { if (session is Character character) { character.Teleport((short)FirstData); } } } break; case BCardType.CardType.CalculatingLevel: break; case BCardType.CardType.Recovery: break; case BCardType.CardType.MaxHPMP: { if (session is Character character) { if (SubType == (byte)AdditionalTypes.MaxHPMP.IncreasesMaximumHP / 10) { character.HPLoad(); character.Session?.SendPacket(character.GenerateStat()); } else if (SubType == (byte)AdditionalTypes.MaxHPMP.IncreasesMaximumMP / 10) { character.MPLoad(); character.Session?.SendPacket(character.GenerateStat()); } } } break; case BCardType.CardType.MultAttack: break; case BCardType.CardType.MultDefence: break; case BCardType.CardType.TimeCircleSkills: break; case BCardType.CardType.RecoveryAndDamagePercent: break; case BCardType.CardType.Count: break; case BCardType.CardType.NoDefeatAndNoDamage: break; case BCardType.CardType.SpecialActions: { Character senderCharacter = sender is ClientSession senderSession ? senderSession.Character : sender as Character; if (SubType == (byte)AdditionalTypes.SpecialActions.PushBack / 10) { if (senderCharacter != null) { if (session is Character character) { if (character.ResistForcedMovementChance <= 0 || ServerManager.RandomNumber() < character.ResistForcedMovementChance) { character.PushBack((short)FirstData, senderCharacter); } } else if (session is MapMonster mapMonster) { mapMonster.PushBack((short)FirstData, senderCharacter); } } } else if (SubType == (byte)AdditionalTypes.SpecialActions.FocusEnemies / 10) { if (senderCharacter != null) { if (session is Character character) { if (character.ResistForcedMovementChance <= 0 || ServerManager.RandomNumber() < character.ResistForcedMovementChance) { character.Focus((short)FirstData, senderCharacter); } } else if (session is MapMonster mapMonster) { mapMonster.Focus((short)FirstData, senderCharacter); } } } else if (SubType == (byte)AdditionalTypes.SpecialActions.Hide / 10) { if (session is Character character) { character.SetInvisible(true); } } } break; case BCardType.CardType.Transform: break; case BCardType.CardType.Mode: break; case BCardType.CardType.NoCharacteristicValue: break; case BCardType.CardType.LightAndShadow: { if (SubType == (byte)AdditionalTypes.LightAndShadow.RemoveBadEffects / 10) { if (session is Character character) { character.Buff?.GetAllItems()?.Where(s => s?.Card?.BuffType == BuffType.Bad && s.Card.Level < FirstData)? .ToList()?.ForEach(s => character.RemoveBuff(s.Card.CardId)); } } } break; case BCardType.CardType.Item: break; case BCardType.CardType.DebuffResistance: break; case BCardType.CardType.SpecialBehaviour: break; case BCardType.CardType.Quest: break; case BCardType.CardType.SecondSPCard: { if (session is Character character) { if (character.MapInstance != null) { List <MonsterToSummon> monsterList = new List <MonsterToSummon>(); if (SubType == (byte)AdditionalTypes.SecondSPCard.PlantBomb / 10) { MapMonster bomb = character.MapInstance.Monsters.FirstOrDefault(m => m?.Owner?.CharacterId == character.CharacterId && m.MonsterVNum == (short)SecondData); if (bomb == null) { for (int i = 0; i < FirstData; i++) { monsterList.Add(new MonsterToSummon((short)SecondData, new MapCell { X = character.PositionX, Y = character.PositionY }, -1, false, false, false, false, false, -1, character, 0, false)); } } else { bomb.Explode(); break; } } else if (SubType == (byte)AdditionalTypes.SecondSPCard.PlantSelfDestructionBomb / 10) { int aliveTime = ServerManager.GetNpc((short)SecondData).RespawnTime; for (int i = 0; i < FirstData; i++) { MapCell mapCell = new MapCell { X = (short)(ServerManager.RandomNumber(-1, 2) + character.PositionX), Y = (short)(ServerManager.RandomNumber(-1, 2) + character.PositionY), }; monsterList.Add(new MonsterToSummon((short)SecondData, mapCell, -1, true, false, false, true, false, -1, character, aliveTime, true)); } } if (monsterList.Any()) { EventHelper.Instance.RunEvent(new EventContainer(character.MapInstance, EventActionType.SPAWNMONSTERS, monsterList)); } } } } break; case BCardType.CardType.SPCardUpgrade: break; case BCardType.CardType.HugeSnowman: break; case BCardType.CardType.Drain: break; case BCardType.CardType.BossMonstersSkill: break; case BCardType.CardType.LordHatus: break; case BCardType.CardType.LordCalvinas: break; case BCardType.CardType.SESpecialist: { if (SubType == (byte)AdditionalTypes.SESpecialist.LowerHPStrongerEffect / 10) { Character senderCharacter = sender is ClientSession senderSession ? senderSession.Character : sender as Character; if (senderCharacter != null) { if (session is Character character) { double percentage = (character.Hp * 100) / character.HPMax; if (percentage < 35) { character.AddBuff(new Buff(274, senderCharacter.Level, senderCharacter)); } else if (percentage < 67) { character.AddBuff(new Buff(273, senderCharacter.Level, senderCharacter)); } else { character.AddBuff(new Buff(272, senderCharacter.Level, senderCharacter)); } } } } } break; case BCardType.CardType.FourthGlacernonFamilyRaid: break; case BCardType.CardType.SummonedMonsterAttack: break; case BCardType.CardType.BearSpirit: { if (session is Character character) { if (SubType == (byte)AdditionalTypes.BearSpirit.IncreaseMaximumHP / 10) { character.HPLoad(); character.Session?.SendPacket(character.GenerateStat()); } else if (SubType == (byte)AdditionalTypes.BearSpirit.IncreaseMaximumMP / 10) { character.MPLoad(); character.Session?.SendPacket(character.GenerateStat()); } } } break; case BCardType.CardType.SummonSkill: break; case BCardType.CardType.InflictSkill: break; case BCardType.CardType.HideBarrelSkill: break; case BCardType.CardType.FocusEnemyAttentionSkill: break; case BCardType.CardType.TauntSkill: break; case BCardType.CardType.FireCannoneerRangeBuff: break; case BCardType.CardType.VulcanoElementBuff: break; case BCardType.CardType.DamageConvertingSkill: break; case BCardType.CardType.MeditationSkill: { if (session is Character character) { if (SkillVNum.HasValue && SubType.Equals((byte)AdditionalTypes.MeditationSkill.CausingChance / 10) && ServerManager.RandomNumber() < FirstData) { Skill skill = ServerManager.GetSkill(SkillVNum.Value); Skill newSkill = ServerManager.GetSkill((short)SecondData); Observable.Timer(TimeSpan.FromMilliseconds(100)).Subscribe(observer => { foreach (QuicklistEntryDTO quicklistEntry in character.QuicklistEntries.Where(s => s.Pos.Equals(skill.CastId))) { character.Session.SendPacket($"qset {quicklistEntry.Q1} {quicklistEntry.Q2} {quicklistEntry.Type}.{quicklistEntry.Slot}.{newSkill.CastId}.0"); } character.Session.SendPacket($"mslot {newSkill.CastId} -1"); }); character.SkillComboCount++; character.LastSkillComboUse = DateTime.Now; if (skill.CastId > 10) { Observable.Timer(TimeSpan.FromMilliseconds((skill.GetCooldown(character) * 100) + 500)).Subscribe(observer => character.Session.SendPacket(StaticPacketHelper.SkillReset(skill.CastId))); } } switch (SubType) { case 2: character.MeditationDictionary[(short)SecondData] = DateTime.Now.AddSeconds(4); break; case 3: character.MeditationDictionary[(short)SecondData] = DateTime.Now.AddSeconds(8); break; case 4: character.MeditationDictionary[(short)SecondData] = DateTime.Now.AddSeconds(12); break; } } } break; case BCardType.CardType.FalconSkill: break; case BCardType.CardType.AbsorptionAndPowerSkill: break; case BCardType.CardType.LeonaPassiveSkill: break; case BCardType.CardType.FearSkill: break; case BCardType.CardType.SniperAttack: break; case BCardType.CardType.FrozenDebuff: break; case BCardType.CardType.JumpBackPush: break; case BCardType.CardType.FairyXPIncrease: break; case BCardType.CardType.SummonAndRecoverHP: break; case BCardType.CardType.TeamArenaBuff: break; case BCardType.CardType.ArenaCamera: break; case BCardType.CardType.DarkCloneSummon: break; case BCardType.CardType.AbsorbedSpirit: break; case BCardType.CardType.AngerSkill: break; case BCardType.CardType.MeteoriteTeleport: break; case BCardType.CardType.StealBuff: break; case BCardType.CardType.Unknown: break; case BCardType.CardType.EffectSummon: break; default: Logger.Warn($"Card Type {Type} Not Found!"); break; } }
private void ExecuteHandler(ClientSession session) { PenaltyLogDTO penalty = session.Account.PenaltyLogs.OrderByDescending(s => s.DateEnd).FirstOrDefault(); if (session.Character.IsMuted() && penalty != null) { if (session.Character.Gender == GenderType.Female) { session.CurrentMapInstance?.Broadcast(session.Character.GenerateSay(Language.Instance.GetMessageFromKey("MUTED_FEMALE"), 1)); session.SendPacket(session.Character.GenerateSay(string.Format(Language.Instance.GetMessageFromKey("MUTE_TIME"), (penalty.DateEnd - DateTime.Now).ToString("hh\\:mm\\:ss")), 11)); } else { session.CurrentMapInstance?.Broadcast(session.Character.GenerateSay(Language.Instance.GetMessageFromKey("MUTED_MALE"), 1)); session.SendPacket(session.Character.GenerateSay(string.Format(Language.Instance.GetMessageFromKey("MUTE_TIME"), (penalty.DateEnd - DateTime.Now).ToString("hh\\:mm\\:ss")), 11)); } return; } Mate attacker = session.Character.Mates.FirstOrDefault(x => x.MateTransportId == MateTransportId); if (attacker?.SpInstance == null || !attacker.IsUsingSp) { return; } short?skillVnum = null; byte value = 0; switch (SkillSlot) { case 0: skillVnum = attacker.SpInstance.FirstPartnerSkill; value = 0; break; case 1: skillVnum = attacker.SpInstance.SecondPartnerSkill; value = 1; break; case 2: skillVnum = attacker.SpInstance.ThirdPartnerSkill; value = 2; break; } if (skillVnum == null) { return; } var mateSkill = ServerManager.GetSkill(skillVnum.Value); if (mateSkill == null) { return; } session.SendPacketAfter($"psr {value}", mateSkill.Cooldown * 100); if (attacker.IsSitting) { return; } attacker.Owner.MapInstance.Broadcast(StaticPacketHelper.GenerateEff(UserType.Npc, attacker.MateTransportId, 5005), attacker.PositionX, attacker.PositionY); switch (TargetType) { case UserType.Monster: if (attacker.Hp <= 0) { return; } var target = session.Character.MapInstance.GetMonster(TargetId); if (target != null) { session.CurrentMapInstance.Broadcast(StaticPacketHelper.CastOnTarget(UserType.Npc, attacker.MateTransportId, 3, target.MapMonsterId, mateSkill.CastAnimation, mateSkill.CastEffect, mateSkill.SkillVNum)); session.CurrentMapInstance.Broadcast(StaticPacketHelper.SkillUsed(UserType.Npc, attacker.MateTransportId, 3, target.MapMonsterId, mateSkill.SkillVNum, mateSkill.Cooldown, mateSkill.AttackAnimation, mateSkill.Effect, target.MapX, target.MapY, target.CurrentHp > 0, (int)(target.CurrentHp / (double)target.MaxHp * 100), 0, 0, 0)); } session.AttackMonster(attacker, mateSkill, TargetId, target?.MapX ?? attacker.PositionX, target?.MapY ?? attacker.PositionY); return; case UserType.Npc: if (attacker.Hp <= 0) { return; } var npcTarget = session.Character.MapInstance.GetNpc(TargetId); if (npcTarget != null) { session.CurrentMapInstance.Broadcast(StaticPacketHelper.CastOnTarget(UserType.Npc, attacker.MateTransportId, 3, npcTarget.MapNpcId, mateSkill.CastAnimation, mateSkill.CastEffect, mateSkill.SkillVNum)); session.CurrentMapInstance.Broadcast(StaticPacketHelper.SkillUsed(UserType.Npc, attacker.MateTransportId, 3, npcTarget.MapNpcId, mateSkill.SkillVNum, mateSkill.Cooldown, mateSkill.AttackAnimation, mateSkill.Effect, npcTarget.MapX, npcTarget.MapY, true, 100, 0, 0, 0)); } session.AttackMonster(attacker, mateSkill, TargetId, npcTarget?.MapX ?? attacker.PositionX, npcTarget?.MapY ?? attacker.PositionY); return; case UserType.Player: return; case UserType.Object: return; default: return; } }
public void ApplyBCards(object session, object sender = null, short buffLevel = 0) { Type type = session.GetType(); // int counterBuff = 0; switch ((BCardType.CardType)Type) { case BCardType.CardType.Buff: { if (type == typeof(Character) && session is Character character) { Buff buff = null; if (sender != null) { Type sType = sender.GetType(); if (sType == typeof(Character) && sender is Character sendingCharacter) { buff = new Buff((short)((short)SecondData + buffLevel), sendingCharacter.Level); //Todo: Get anti stats from BCard } } else { buff = new Buff((short)((short)SecondData + buffLevel), character.Level); } int anti = 0; if (buff?.Card.BuffType == BuffType.Bad) { anti += character.ShellEffectArmor?.FirstOrDefault(s => s.Effect == (byte)ShellArmorEffectType.ReducedAllNegativeEffect)?.Value ?? 0; switch (SecondData) { case 1: anti += character.ShellEffectArmor?.FirstOrDefault(s => s.Effect == (byte)ShellArmorEffectType .ReducedBleedingAndMinorBleeding) ?.Value ?? 0; anti += character.ShellEffectArmor?.FirstOrDefault(s => s.Effect == (byte)ShellArmorEffectType.ReducedAllBleedingType) ?.Value ?? 0; break; case 7: anti += character.ShellEffectArmor ?.FirstOrDefault(s => s.Effect == (byte)ShellArmorEffectType.ReducedStun)?.Value ?? 0; anti += character.ShellEffectArmor?.FirstOrDefault(s => s.Effect == (byte)ShellArmorEffectType.ReducedAllStun)?.Value ?? 0; break; case 21: anti += character.ShellEffectArmor?.FirstOrDefault(s => s.Effect == (byte)ShellArmorEffectType.ReducedMinorBleeding)?.Value ?? 0; anti += character.ShellEffectArmor?.FirstOrDefault(s => s.Effect == (byte)ShellArmorEffectType .ReducedBleedingAndMinorBleeding) ?.Value ?? 0; anti += character.ShellEffectArmor?.FirstOrDefault(s => s.Effect == (byte)ShellArmorEffectType.ReducedAllBleedingType) ?.Value ?? 0; break; case 27: anti += character.ShellEffectArmor?.FirstOrDefault(s => s.Effect == (byte)ShellArmorEffectType.ReducedFreeze)?.Value ?? 0; break; case 42: anti += character.ShellEffectArmor?.FirstOrDefault(s => s.Effect == (byte)ShellArmorEffectType.ReducedAllBleedingType) ?.Value ?? 0; break; case 66: anti += character.ShellEffectArmor?.FirstOrDefault(s => s.Effect == (byte)ShellArmorEffectType.ReducedAllStun)?.Value ?? 0; break; } } if (ServerManager.RandomNumber() < FirstData / 100D * (100 - anti)) { character.AddBuff(buff); } } else if (type == typeof(MapMonster)) { if (ServerManager.RandomNumber() < FirstData && session is MapMonster mapMonster) { mapMonster.AddBuff(new Buff((short)((short)SecondData + buffLevel), mapMonster.Monster.Level)); } } else if (type == typeof(MapNpc)) { } else if (type == typeof(Mate)) { } } break; case BCardType.CardType.Move: { if (type == typeof(Character) && session is Character character) { character.LastSpeedChange = DateTime.UtcNow; character.Session.SendPacket(character.GenerateCond()); } } break; case BCardType.CardType.Summons: { if (type == typeof(Character)) { // jajamaru spawn if (session is Character character && character.MapInstance != null) { List <MonsterToSummon> summonParameters = new List <MonsterToSummon>(); for (int i = 0; i < FirstData; i++) { short x, y; byte t = 0; do { x = (short)(ServerManager.RandomNumber(-3, 3) + character.PositionX); y = (short)(ServerManager.RandomNumber(-3, 3) + character.PositionY); t++; } while (!character.MapInstance.Map.IsBlockedZone(x, y) && t < byte.MaxValue); summonParameters.Add(new MonsterToSummon((short)SecondData, new MapCell { X = x, Y = y }, -1, true)); } if (ServerManager.RandomNumber() <= Math.Abs(ThirdData) || ThirdData == 0) { switch (SubType) { case 2: EventHelper.Instance.RunEvent(new EventContainer( character.Session.CurrentMapInstance, EventActionType.SpawnMonsters, summonParameters)); break; } } } } else if (type == typeof(MapMonster)) { if (session is MapMonster mapMonster && mapMonster.MapInstance != null) { List <MonsterToSummon> summonParameters = new List <MonsterToSummon>(); for (int i = 0; i < FirstData; i++) { short x, y; byte t = 0; do { x = (short)(ServerManager.RandomNumber(-3, 3) + mapMonster.MapX); y = (short)(ServerManager.RandomNumber(-3, 3) + mapMonster.MapY); t++; } while (!mapMonster.MapInstance.Map.IsBlockedZone(x, y) && t < byte.MaxValue); summonParameters.Add(new MonsterToSummon((short)SecondData, new MapCell { X = x, Y = y }, -1, true)); } if (ServerManager.RandomNumber() <= Math.Abs(ThirdData) || ThirdData == 0) { switch (SubType) { case 2: EventHelper.Instance.RunEvent(new EventContainer(mapMonster.MapInstance, EventActionType.SpawnMonsters, summonParameters)); break; default: if (mapMonster.OnDeathEvents.All(s => s.EventActionType != EventActionType.SpawnMonsters)) { mapMonster.OnDeathEvents.Add(new EventContainer(mapMonster.MapInstance, EventActionType.SpawnMonsters, summonParameters)); } break; } } } } else if (type == typeof(MapNpc)) { } else if (type == typeof(Mate)) { } } break; case BCardType.CardType.SpecialAttack: break; case BCardType.CardType.SpecialDefence: break; case BCardType.CardType.AttackPower: break; case BCardType.CardType.Target: break; case BCardType.CardType.Critical: break; case BCardType.CardType.SpecialCritical: break; case BCardType.CardType.Element: break; case BCardType.CardType.IncreaseDamage: break; case BCardType.CardType.Defence: break; case BCardType.CardType.DodgeAndDefencePercent: break; case BCardType.CardType.Block: break; case BCardType.CardType.Absorption: break; case BCardType.CardType.ElementResistance: break; case BCardType.CardType.EnemyElementResistance: break; case BCardType.CardType.Damage: break; case BCardType.CardType.GuarantedDodgeRangedAttack: break; case BCardType.CardType.Morale: break; case BCardType.CardType.Casting: break; case BCardType.CardType.Reflection: break; case BCardType.CardType.DrainAndSteal: break; case BCardType.CardType.HealingBurningAndCasting: { if (type == typeof(Character)) { if (session is Character character && character.Hp > 0) { int bonus; if (SubType == (byte)AdditionalTypes.HealingBurningAndCasting.RestoreHP / 10) { if (IsLevelScaled) { bonus = character.Level * FirstData; } else { bonus = FirstData; } if (character.Hp + bonus <= character.HPLoad()) { character.Hp += bonus; } else { bonus = (int)character.HPLoad() - character.Hp; character.Hp = (int)character.HPLoad(); } character.Session.CurrentMapInstance?.Broadcast(character.Session, character.GenerateRc(bonus)); } if (SubType == (byte)AdditionalTypes.HealingBurningAndCasting.RestoreMP / 10) { if (IsLevelScaled) { bonus = character.Level * FirstData; } else { bonus = FirstData; } if (character.Mp + bonus <= character.MPLoad()) { character.Mp += bonus; } else { character.Mp = (int)character.MPLoad(); } } character.Session.SendPacket(character.GenerateStat()); } } else if (type == typeof(MapMonster)) { if (ServerManager.RandomNumber() < FirstData && session is MapMonster mapMonster) { mapMonster.AddBuff(new Buff((short)SecondData, mapMonster.Monster.Level)); } } else if (type == typeof(MapNpc)) { } else if (type == typeof(Mate)) { } } break; case BCardType.CardType.Hpmp: if (type == typeof(Character)) { if (session is Character c) { switch (SubType) { case (byte)AdditionalTypes.Hpmp.RestoreDecreasedMP / 10: { int bonus = (int)(FirstData * c.MPLoad() / 100); c.Mp = c.Mp + bonus > 1 ? c.Mp + bonus : c.Mp = 1; } break; } } } break; case BCardType.CardType.SpecialisationBuffResistance: { switch (SubType) { case (byte)AdditionalTypes.SpecialisationBuffResistance.RemoveBadEffects / 10: { if (session is Character c && /*&& sender is ClientSession senderSession*/ ServerManager.RandomNumber() < Math.Abs(FirstData)) { c.DisableBuffs(FirstData > 0 ? BuffType.Good : BuffType.Bad, SecondData); } } break; } } break; case BCardType.CardType.SpecialEffects: break; case BCardType.CardType.Capture: { if (type == typeof(MapMonster) && session is MapMonster mapMonster && sender is ClientSession senderSession) { NpcMonster mateNpc = ServerManager.GetNpcMonster(mapMonster.MonsterVNum); if (mateNpc != null) { if (mapMonster.Monster.Catch) { if (mapMonster.IsAlive && mapMonster.CurrentHp <= (int)((double)mapMonster.MaxHp / 2)) { if (mapMonster.Monster.Level < senderSession.Character.Level) { // TODO: find a new algorithm int[] chance = { 100, 80, 60, 40, 20, 0 }; if (ServerManager.RandomNumber() < chance[ServerManager.RandomNumber(0, 5)]) { Mate mate = new Mate(senderSession.Character, mateNpc, (byte)(mapMonster.Monster.Level - 15 > 0 ? mapMonster.Monster.Level - 15 : 1), MateType.Pet); if (senderSession.Character.CanAddMate(mate)) { senderSession.Character.AddPetWithSkill(mate); senderSession.SendPacket( UserInterfaceHelper.GenerateMsg( Language.Instance.GetMessageFromKey("CATCH_SUCCESS"), 0)); senderSession.CurrentMapInstance?.Broadcast( StaticPacketHelper.GenerateEff(UserType.Player, senderSession.Character.CharacterId, 197)); senderSession.CurrentMapInstance?.Broadcast( StaticPacketHelper.SkillUsed(UserType.Player, senderSession.Character.CharacterId, 3, mapMonster.MapMonsterId, -1, 0, 15, -1, -1, -1, true, (int)(mapMonster.CurrentHp / (float)mapMonster.MaxHp * 100 ), 0, -1, 0)); mapMonster.SetDeathStatement(); senderSession.CurrentMapInstance?.Broadcast( StaticPacketHelper.Out(UserType.Monster, mapMonster.MapMonsterId)); } else { senderSession.SendPacket( senderSession.Character.GenerateSay( Language.Instance.GetMessageFromKey("PET_SLOT_FULL"), 10)); senderSession.SendPacket( StaticPacketHelper.Cancel(2, mapMonster.MapMonsterId)); } } else { senderSession.SendPacket( UserInterfaceHelper.GenerateMsg( Language.Instance.GetMessageFromKey("CATCH_FAIL"), 0)); senderSession.CurrentMapInstance?.Broadcast( StaticPacketHelper.SkillUsed(UserType.Player, senderSession.Character.CharacterId, 3, mapMonster.MapMonsterId, -1, 0, 15, -1, -1, -1, true, (int)(mapMonster.CurrentHp / (float)mapMonster.MaxHp * 100), 0, -1, 0)); } } else { senderSession.SendPacket(UserInterfaceHelper.GenerateMsg( Language.Instance.GetMessageFromKey("LEVEL_LOWER_THAN_MONSTER"), 0)); senderSession.SendPacket( StaticPacketHelper.Cancel(2, mapMonster.MapMonsterId)); } } else { senderSession.SendPacket(UserInterfaceHelper.GenerateMsg( Language.Instance.GetMessageFromKey("CURRENT_HP_TOO_HIGH"), 0)); senderSession.SendPacket(StaticPacketHelper.Cancel(2, mapMonster.MapMonsterId)); } } else { senderSession.SendPacket(UserInterfaceHelper.GenerateMsg( Language.Instance.GetMessageFromKey("MONSTER_CANT_BE_CAPTURED"), 0)); senderSession.SendPacket(StaticPacketHelper.Cancel(2, mapMonster.MapMonsterId)); } } } } break; case BCardType.CardType.SpecialDamageAndExplosions: break; case BCardType.CardType.SpecialEffects2: if (type == typeof(Character)) { if (session is Character c) { short destinationX = c.PositionX; short destinationY = c.PositionY; switch (SubType) { case (byte)AdditionalTypes.SpecialEffects2.TeleportInRadius / 10: { switch (c.Direction) { case 0: // -y destinationY -= (short)FirstData; break; case 1: // +x destinationX += (short)FirstData; break; case 2: // +y destinationY += (short)FirstData; break; case 3: // -x destinationX -= (short)FirstData; break; case 4: // -x -y destinationX -= (short)FirstData; destinationY -= (short)FirstData; break; case 5: // +x +y destinationX += (short)FirstData; destinationY += (short)FirstData; break; case 6: // +x -y destinationX += (short)FirstData; destinationY -= (short)FirstData; break; case 7: // -x +y destinationX -= (short)FirstData; destinationY += (short)FirstData; break; } ServerManager.Instance.TeleportForward(c.Session, c.MapInstanceId, destinationX, destinationY); } break; } } } break; case BCardType.CardType.CalculatingLevel: break; case BCardType.CardType.Recovery: break; case BCardType.CardType.MaxHpmp: break; case BCardType.CardType.MultAttack: break; case BCardType.CardType.MultDefence: break; case BCardType.CardType.TimeCircleSkills: break; case BCardType.CardType.RecoveryAndDamagePercent: break; case BCardType.CardType.Count: break; case BCardType.CardType.NoDefeatAndNoDamage: break; case BCardType.CardType.SpecialActions: { switch (SubType) { case (byte)AdditionalTypes.SpecialActions.RunAway / 10: if (session is MapMonster m) { m.MapInstance.Broadcast(StaticPacketHelper.Say(UserType.Monster, m.MapMonsterId, 0, "!!!")); m.RemoveTarget(); for (int i = 0; i < 10; i++) { Observable.Timer(TimeSpan.FromSeconds(i)).Subscribe(o => { m.MapX++; m.MapY++; m.IgnoreTargetsUntil = DateTime.UtcNow.AddSeconds(10); m.RemoveTarget(); }); } } break; } } break; case BCardType.CardType.Mode: break; case BCardType.CardType.NoCharacteristicValue: break; case BCardType.CardType.LightAndShadow: { switch (SubType) { case (byte)AdditionalTypes.LightAndShadow.RemoveBadEffects / 10: { if (session is Character c /*&& sender is ClientSession senderSession*/) { c.DisableBuffs(BuffType.Bad, FirstData); } } break; } } break; case BCardType.CardType.Item: break; case BCardType.CardType.DebuffResistance: break; case BCardType.CardType.SpecialBehaviour: break; case BCardType.CardType.Quest: break; case BCardType.CardType.SecondSpCard: break; case BCardType.CardType.SpCardUpgrade: break; case BCardType.CardType.HugeSnowman: break; case BCardType.CardType.Drain: break; case BCardType.CardType.BossMonstersSkill: break; case BCardType.CardType.LordHatus: break; case BCardType.CardType.LordCalvinas: break; case BCardType.CardType.SeSpecialist: break; case BCardType.CardType.FourthGlacernonFamilyRaid: break; case BCardType.CardType.SummonedMonsterAttack: break; case BCardType.CardType.BearSpirit: break; case BCardType.CardType.SummonSkill: break; case BCardType.CardType.InflictSkill: break; case BCardType.CardType.HideBarrelSkill: break; case BCardType.CardType.FocusEnemyAttentionSkill: break; case BCardType.CardType.TauntSkill: break; case BCardType.CardType.FireCannoneerRangeBuff: break; case BCardType.CardType.VulcanoElementBuff: break; case BCardType.CardType.DamageConvertingSkill: break; case BCardType.CardType.MeditationSkill: { if (type == typeof(Character) && session is Character character) { if (SkillVNum.HasValue && SubType.Equals((byte)AdditionalTypes.MeditationSkill.CausingChance / 10) && ServerManager.RandomNumber() < FirstData) { Skill skill = ServerManager.GetSkill(SkillVNum.Value); Skill newSkill = ServerManager.GetSkill((short)SecondData); Observable.Timer(TimeSpan.FromMilliseconds(100)).Subscribe(observer => { foreach (QuicklistEntryDTO quicklistEntry in character.QuicklistEntries.Where(s => s.Morph == character.Morph && s.Pos.Equals(skill.CastId))) { character.Session.SendPacket( $"qset {quicklistEntry.Q1} {quicklistEntry.Q2} {quicklistEntry.Type}.{quicklistEntry.Slot}.{newSkill.CastId}.0"); } character.Session.SendPacket($"mslot {newSkill.CastId} -1"); }); character.SkillComboCount++; character.LastSkillComboUse = DateTime.UtcNow; if (skill.CastId > 10) { // HACK this way Observable.Timer(TimeSpan.FromMilliseconds((skill.Cooldown * 100) + 500)) .Subscribe(observer => character.Session.SendPacket(StaticPacketHelper.SkillReset(skill.CastId))); } } switch (SubType) { case 2: character.MeditationDictionary[(short)SecondData] = DateTime.UtcNow.AddSeconds(4); break; case 3: character.MeditationDictionary[(short)SecondData] = DateTime.UtcNow.AddSeconds(8); break; case 4: character.MeditationDictionary[(short)SecondData] = DateTime.UtcNow.AddSeconds(12); break; } } } break; case BCardType.CardType.FalconSkill: { if (session is Character c) { switch (SubType) { case (byte)AdditionalTypes.FalconSkill.Hide: c.Invisible = true; c.Mates.Where(s => s.IsTeamMember).ToList().ForEach(s => c.Session.CurrentMapInstance?.Broadcast(s.GenerateOut())); c.Session.CurrentMapInstance?.Broadcast(c.GenerateInvisible()); c.Session.SendPacket(c.GenerateEq()); break; } } } break; case BCardType.CardType.AbsorptionAndPowerSkill: break; case BCardType.CardType.LeonaPassiveSkill: break; case BCardType.CardType.FearSkill: break; case BCardType.CardType.SniperAttack: break; case BCardType.CardType.FrozenDebuff: break; case BCardType.CardType.JumpBackPush: break; case BCardType.CardType.FairyXPIncrease: break; case BCardType.CardType.SummonAndRecoverHP: break; case BCardType.CardType.TeamArenaBuff: break; case BCardType.CardType.ArenaCamera: break; case BCardType.CardType.DarkCloneSummon: break; case BCardType.CardType.AbsorbedSpirit: break; case BCardType.CardType.AngerSkill: break; case BCardType.CardType.MeteoriteTeleport: if (type == typeof(Character)) { if (session is Character character) { switch (SubType) { case ((byte)AdditionalTypes.MeteoriteTeleport.TeleportYouAndGroupToSavedLocation / 10): if (character.TeleportSet == false) { character.TeleportX = character.PositionX; character.TeleportY = character.PositionY; character.TeleportMap = character.MapId; character.MapInstance.Broadcast(StaticPacketHelper.GenerateEff(UserType.Player, character.CharacterId, 4497)); character.TeleportSet = true; Observable.Timer(TimeSpan.FromSeconds(40)).Subscribe(o => character.TeleportSet = false); } else { if (character.MapInstance.IsPvp) { if (character.MapInstance.MapInstanceType != MapInstanceType.BaseMapInstance) { character.TeleportSet = false; return; } character.MapInstance.Broadcast($"tp 1 {character.CharacterId} {character.TeleportX} {character.TeleportY} 0"); character.PositionX = character.TeleportX; character.PositionY = character.TeleportY; character.TeleportSet = false; } else { if (character.MapId == character.TeleportMap) { if (character.MapInstance.MapInstanceType == MapInstanceType.CaligorInstance) { character.TeleportSet = false; return; } character.MapInstance.Broadcast($"tp 1 {character.CharacterId} {character.TeleportX} {character.TeleportY} 0"); character.PositionX = character.TeleportX; character.PositionY = character.TeleportY; character.TeleportSet = false; } else { character.TeleportSet = false; } } } break; case (byte)AdditionalTypes.MeteoriteTeleport.CauseMeteoriteFall / 10: { int amount = 10 + (character.Level / FirstData); for (int i = 0; i < amount; i++) { Observable.Timer(TimeSpan.FromMilliseconds(i * 500)).Subscribe(o => character.SpawnMeteorite()); } } break; } } } break; case BCardType.CardType.StealBuff: break; case BCardType.CardType.Unknown: break; case BCardType.CardType.EffectSummon: break; default: Logger.Warn($"Card Type {Type} not defined!"); break; } }
private void ExecuteHandler(ClientSession session) { PenaltyLogDTO penalty = session.Account.PenaltyLogs.OrderByDescending(s => s.DateEnd).FirstOrDefault(); if (session.Character.IsMuted() && penalty != null) { if (session.Character.Gender == GenderType.Female) { session.CurrentMapInstance?.Broadcast(session.Character.GenerateSay(Language.Instance.GetMessageFromKey("MUTED_FEMALE"), 1)); session.SendPacket(session.Character.GenerateSay(string.Format(Language.Instance.GetMessageFromKey("MUTE_TIME"), (penalty.DateEnd - DateTime.Now).ToString("hh\\:mm\\:ss")), 11)); } else { session.CurrentMapInstance?.Broadcast(session.Character.GenerateSay(Language.Instance.GetMessageFromKey("MUTED_MALE"), 1)); session.SendPacket(session.Character.GenerateSay(string.Format(Language.Instance.GetMessageFromKey("MUTE_TIME"), (penalty.DateEnd - DateTime.Now).ToString("hh\\:mm\\:ss")), 11)); } return; } Mate attacker = session.Character.Mates.FirstOrDefault(x => x.MateTransportId == MateTransportId); if (attacker == null) { return; } NpcMonsterSkill mateSkill = null; if (attacker.Monster.Skills.Any()) { mateSkill = attacker.Monster.Skills.FirstOrDefault(sk => MateHelper.Instance.PetSkills.Contains(sk.SkillVNum)); } if (mateSkill == null) { mateSkill = new NpcMonsterSkill { SkillVNum = 200 }; } if (attacker.IsSitting) { return; } MapMonster target = session.CurrentMapInstance?.GetMonster(TargetId); switch (TargetType) { case UserType.Monster: case UserType.Npc: if (attacker.Hp <= 0) { return; } if (target != null) { session.CurrentMapInstance.Broadcast(StaticPacketHelper.CastOnTarget(UserType.Npc, attacker.MateTransportId, 3, target.MapMonsterId, mateSkill.Skill.CastAnimation, mateSkill.Skill.CastEffect, mateSkill.SkillVNum)); session.CurrentMapInstance.Broadcast(StaticPacketHelper.SkillUsed(UserType.Npc, attacker.MateTransportId, 3, target.MapMonsterId, mateSkill.SkillVNum, mateSkill.Skill.Cooldown, mateSkill.Skill.AttackAnimation, mateSkill.Skill.Effect, target.MapX, target.MapY, target.CurrentHp > 0, (int)(target.CurrentHp / (double)target.MaxHp * 100), 0, 0, 0)); } session.AttackMonster(attacker, mateSkill.Skill, TargetId, target?.MapX ?? attacker.PositionX, target?.MapY ?? attacker.PositionY); session.SendPacketAfter("petsr 0", mateSkill.Skill.Cooldown * 100); return; case UserType.Player: if (attacker.Hp <= 0) { return; } Character targetChar = session.CurrentMapInstance?.GetSessionByCharacterId(TargetId) ?.Character; if (targetChar != null && session.CurrentMapInstance != null && (targetChar.Session.CurrentMapInstance == session.CurrentMapInstance && targetChar.CharacterId != session.Character.CharacterId && session.CurrentMapInstance.Map.MapTypes.Any(s => s.MapTypeId == (short)MapTypeEnum.Act4) && session.Character.Faction != targetChar.Faction && session.CurrentMapInstance.Map .MapId != 130 && session.CurrentMapInstance.Map .MapId != 131 || session.CurrentMapInstance.Map.MapTypes.Any(m => m.MapTypeId == (short)MapTypeEnum.PvpMap) && (session.Character.Group == null || !session.Character.Group .IsMemberOfGroup( targetChar.CharacterId)) || session.CurrentMapInstance.IsPvp && (session.Character.Group == null || !session.Character.Group.IsMemberOfGroup( targetChar.CharacterId)))) { session.AttackCharacter(attacker, mateSkill, targetChar); } return; case UserType.Object: return; default: return; } }