/// <summary> /// Remove the current Target from Npc. /// </summary> internal void RemoveTarget() { Target = null; Path = BestFirstSearch.FindPath(new Node { X = MapX, Y = MapY }, new Node { X = FirstX, Y = FirstY }, MapInstance.Map.Grid); // Path To origins }
/// <summary> /// Remove the current Target from Npc. /// </summary> internal void RemoveTarget() { if (Target != -1) { Path.Clear(); Target = -1; //return to origin Path = BestFirstSearch.FindPath(new Node { X = MapX, Y = MapY }, new Node { X = FirstX, Y = FirstY }, MapInstance.Map.Grid); } }
/// <summary> /// Remove the current Target from Monster. /// </summary> internal void RemoveTarget() { GetNearestOponent(); if (Target != null) { Path.Clear(); return; } Path = BestFirstSearch.FindPath(new Node { X = MapX, Y = MapY }, new Node { X = FirstX, Y = FirstY }, MapInstance.Map.Grid); // Path To origins }
/// <summary> /// Run Event /// </summary> /// <param name="evt">Event Container</param> /// <param name="session">Character Session that run the event</param> /// <param name="monster">Monster that run the event</param> public void RunEvent(EventContainer evt, ClientSession session = null, MapMonster monster = null) { if (session != null) { evt.MapInstance = session.CurrentMapInstance; switch (evt.EventActionType) { #region EventForUser case EventActionType.NPCDIALOG: session.SendPacket(session.Character.GenerateNpcDialog((int)evt.Parameter)); break; case EventActionType.SENDPACKET: session.SendPacket((string)evt.Parameter); break; #endregion } } if (evt.MapInstance == null) { return; } switch (evt.EventActionType) { #region EventForUser case EventActionType.NPCDIALOG: case EventActionType.SENDPACKET: if (session == null) { evt.MapInstance.Sessions.ToList().ForEach(e => { RunEvent(evt, e); }); } break; #endregion #region MapInstanceEvent case EventActionType.REGISTEREVENT: Tuple <string, ConcurrentBag <EventContainer> > even = (Tuple <string, ConcurrentBag <EventContainer> >)evt.Parameter; switch (even.Item1) { case "OnCharacterDiscoveringMap": even.Item2.ToList().ForEach(s => evt.MapInstance.OnCharacterDiscoveringMapEvents.Add(new Tuple <EventContainer, List <long> >(s, new List <long>()))); break; case "OnMoveOnMap": evt.MapInstance.OnMoveOnMapEvents.AddRange(even.Item2); break; case "OnMapClean": evt.MapInstance.OnMapClean.AddRange(even.Item2); break; case "OnLockerOpen": even.Item2.ToList().ForEach(s => evt.MapInstance.InstanceBag.UnlockEvents.Add(s)); break; } break; case EventActionType.REGISTERWAVE: evt.MapInstance.WaveEvents.Add((EventWave)evt.Parameter); break; case EventActionType.SETAREAENTRY: ZoneEvent even2 = (ZoneEvent)evt.Parameter; evt.MapInstance.OnAreaEntryEvents.Add(even2); break; case EventActionType.REMOVEMONSTERLOCKER: if (evt.MapInstance.InstanceBag.MonsterLocker.Current > 0) { evt.MapInstance.InstanceBag.MonsterLocker.Current--; } if (evt.MapInstance.InstanceBag.MonsterLocker.Current == 0 && evt.MapInstance.InstanceBag.ButtonLocker.Current == 0) { evt.MapInstance.InstanceBag.UnlockEvents.ToList().ForEach(s => RunEvent(s)); evt.MapInstance.InstanceBag.UnlockEvents.Clear(); } break; case EventActionType.REMOVEBUTTONLOCKER: if (evt.MapInstance.InstanceBag.ButtonLocker.Current > 0) { evt.MapInstance.InstanceBag.ButtonLocker.Current--; } if (evt.MapInstance.InstanceBag.MonsterLocker.Current == 0 && evt.MapInstance.InstanceBag.ButtonLocker.Current == 0) { evt.MapInstance.InstanceBag.UnlockEvents.ToList().ForEach(s => RunEvent(s)); evt.MapInstance.InstanceBag.UnlockEvents.Clear(); } break; case EventActionType.EFFECT: short evt3 = (short)evt.Parameter; if (monster != null && (DateTime.Now - monster.LastEffect).TotalSeconds >= 5) { evt.MapInstance.Broadcast(monster.GenerateEff(evt3)); monster.ShowEffect(); } break; case EventActionType.CONTROLEMONSTERINRANGE: if (monster != null) { Tuple <short, byte, ConcurrentBag <EventContainer> > evnt = (Tuple <short, byte, ConcurrentBag <EventContainer> >)evt.Parameter; List <MapMonster> mapMonsters = evt.MapInstance.GetListMonsterInRange(monster.MapX, monster.MapY, evnt.Item2); if (evnt.Item1 != 0) { mapMonsters.RemoveAll(s => s.MonsterVNum != evnt.Item1); } mapMonsters.ForEach(s => evnt.Item3.ToList().ForEach(e => RunEvent(e, monster: s))); } break; case EventActionType.ONTARGET: if (monster?.MoveEvent != null && monster.MoveEvent.InZone(monster.MapX, monster.MapY)) { ((ConcurrentBag <EventContainer>)evt.Parameter).ToList().ForEach(s => RunEvent(s, monster: monster)); } break; case EventActionType.MOVE: ZoneEvent evt4 = (ZoneEvent)evt.Parameter; if (monster != null) { monster.FirstX = evt4.X; monster.FirstY = evt4.Y; monster.MoveEvent = evt4; monster.Path = BestFirstSearch.FindPath(new Node { X = monster.MapX, Y = monster.MapY }, new Node { X = evt4.X, Y = evt4.Y }, evt.MapInstance?.Map.Grid); } break; case EventActionType.CLOCK: evt.MapInstance.InstanceBag.Clock.BasesSecondRemaining = Convert.ToInt32(evt.Parameter); evt.MapInstance.InstanceBag.Clock.DeciSecondRemaining = Convert.ToInt32(evt.Parameter); break; case EventActionType.SETMONSTERLOCKERS: evt.MapInstance.InstanceBag.MonsterLocker.Current = Convert.ToByte(evt.Parameter); evt.MapInstance.InstanceBag.MonsterLocker.Initial = Convert.ToByte(evt.Parameter); break; case EventActionType.SETBUTTONLOCKERS: evt.MapInstance.InstanceBag.ButtonLocker.Current = Convert.ToByte(evt.Parameter); evt.MapInstance.InstanceBag.ButtonLocker.Initial = Convert.ToByte(evt.Parameter); break; case EventActionType.SCRIPTEND: switch (evt.MapInstance.MapInstanceType) { case MapInstanceType.TimeSpaceInstance: evt.MapInstance.InstanceBag.EndState = (byte)evt.Parameter; ClientSession client = evt.MapInstance.Sessions.FirstOrDefault(); if (client != null) { Guid mapInstanceId = ServerManager.Instance.GetBaseMapInstanceIdByMapId(client.Character.MapId); MapInstance map = ServerManager.Instance.GetMapInstance(mapInstanceId); ScriptedInstance si = map.ScriptedInstances.FirstOrDefault(s => s.PositionX == client.Character.MapX && s.PositionY == client.Character.MapY); byte penalty = 0; if (si != null && penalty > (client.Character.Level - si.LevelMinimum) * 2) { penalty = penalty > 100 ? (byte)100 : penalty; client.SendPacket(client.Character.GenerateSay(string.Format(Language.Instance.GetMessageFromKey("TS_PENALTY"), penalty), 10)); } int point = evt.MapInstance.InstanceBag.Point * (100 - penalty) / 100; string perfection = string.Empty; perfection += si != null && evt.MapInstance.InstanceBag.MonstersKilled >= si.MonsterAmount ? 1 : 0; perfection += evt.MapInstance.InstanceBag.NpcsKilled == 0 ? 1 : 0; perfection += si != null && evt.MapInstance.InstanceBag.RoomsVisited >= si.RoomAmount ? 1 : 0; if (si != null) { evt.MapInstance.Broadcast( $"score {evt.MapInstance.InstanceBag.EndState} {point} 27 47 18 {si.DrawItems.Count()} {evt.MapInstance.InstanceBag.MonstersKilled} {si.NpcAmount - evt.MapInstance.InstanceBag.NpcsKilled} {evt.MapInstance.InstanceBag.RoomsVisited} {perfection} 1 1"); } } break; case MapInstanceType.RaidInstance: evt.MapInstance.InstanceBag.EndState = (byte)evt.Parameter; client = evt.MapInstance.Sessions.FirstOrDefault(); List <ClientSession> toBan = new List <ClientSession>(); if (client != null) { Group grp = client.Character?.Group; if (grp == null) { return; } if (evt.MapInstance.InstanceBag.EndState == 1 && evt.MapInstance.Monsters.Any(s => s.IsBoss && !s.IsAlive)) { foreach (ClientSession sess in grp.Characters.Replace(s => s.CurrentMapInstance.Monsters.Any(e => e.IsBoss))) { // TODO REMOTE THAT FOR PUBLIC RELEASE if (grp.Characters.Count(s => s.IpAddress.Equals(sess.IpAddress)) > 2) { toBan.Add(sess); continue; } if (grp.Raid?.GiftItems == null) { continue; } if (grp.Raid.Reputation > 0) { sess.Character.GetReput(grp.Raid.Reputation); } if (sess.Character.Dignity < 0) { sess.Character.Dignity += 100; } else { sess.Character.Dignity = 100; } if (sess.Character.Level > grp.Raid.LevelMaximum) { // RAID CERTIFICATE sess.Character.GiftAdd(2320, 1); } else { foreach (Gift gift in grp.Raid?.GiftItems) { sbyte rare = 0; if (gift.IsRandomRare) { rare = (sbyte)ServerManager.Instance.RandomNumber(-2, 7); } //TODO add random rarity for some object sess.Character.GiftAdd(gift.VNum, gift.Amount, gift.Design, rare: rare); } } } // Remove monster when raid is over foreach (MapMonster e in evt.MapInstance.Monsters.Where(s => !s.IsBoss)) { evt.MapInstance.DespawnMonster(e.MonsterVNum); } evt.MapInstance.WaveEvents.Clear(); ServerManager.Instance.Broadcast(UserInterfaceHelper.Instance.GenerateMsg( string.Format(Language.Instance.GetMessageFromKey("RAID_SUCCEED"), grp.Raid?.Label, grp.Characters.ElementAt(0).Character.Name), 0)); Observable.Timer(TimeSpan.FromSeconds(evt.MapInstance.InstanceBag.EndState == 1 ? 30 : 0)).Subscribe(obj => { ClientSession[] grpmembers = new ClientSession[40]; grp.Characters.ToList().CopyTo(grpmembers); List <MapInstance> mapinstances = new List <MapInstance>(); foreach (ClientSession targetSession in grpmembers) { if (targetSession == null) { continue; } if (targetSession.Character.Hp <= 0) { targetSession.Character.Hp = 1; targetSession.Character.Mp = 1; } targetSession.SendPacket(targetSession.Character.GenerateRaidBf(evt.MapInstance.InstanceBag.EndState)); targetSession.SendPacket(targetSession.Character.GenerateRaid(1, true)); targetSession.SendPacket(targetSession.Character.GenerateRaid(2, true)); if (!mapinstances.Any(s => s.MapInstanceId == targetSession?.CurrentMapInstance.MapInstanceId && s.MapInstanceType == MapInstanceType.RaidInstance)) { mapinstances.Add(targetSession.CurrentMapInstance); } grp.LeaveGroup(targetSession); } ServerManager.Instance.GroupList.RemoveAll(s => s.GroupId == grp.GroupId); ServerManager.Instance.GroupsThreadSafe.TryRemove(grp.GroupId, out Group _); mapinstances.ForEach(s => s.Dispose()); }); } } break; } break; case EventActionType.MAPCLOCK: evt.MapInstance.Clock.BasesSecondRemaining = Convert.ToInt32(evt.Parameter); evt.MapInstance.Clock.DeciSecondRemaining = Convert.ToInt32(evt.Parameter); break; case EventActionType.STARTCLOCK: Tuple <List <EventContainer>, List <EventContainer> > eve = (Tuple <List <EventContainer>, List <EventContainer> >)evt.Parameter; if (eve != null) { evt.MapInstance.InstanceBag.Clock.StopEvents = eve.Item2; evt.MapInstance.InstanceBag.Clock.TimeoutEvents = eve.Item1; evt.MapInstance.InstanceBag.Clock.StartClock(); evt.MapInstance.Broadcast(evt.MapInstance.InstanceBag.Clock.GetClock()); } break; case EventActionType.TELEPORT: Tuple <short, short, short, short> tp = (Tuple <short, short, short, short>)evt.Parameter; List <Character> characters = evt.MapInstance.GetCharactersInRange(tp.Item1, tp.Item2, 5).ToList(); characters.ForEach(s => { s.PositionX = tp.Item3; s.PositionY = tp.Item4; evt.MapInstance?.Broadcast(s.Session, s.GenerateTp(), ReceiverType.Group); }); break; case EventActionType.STOPCLOCK: evt.MapInstance.InstanceBag.Clock.StopClock(); evt.MapInstance.Broadcast(evt.MapInstance.InstanceBag.Clock.GetClock()); break; case EventActionType.STARTMAPCLOCK: eve = (Tuple <List <EventContainer>, List <EventContainer> >)evt.Parameter; if (eve != null) { evt.MapInstance.Clock.StopEvents = eve.Item2; evt.MapInstance.Clock.TimeoutEvents = eve.Item1; evt.MapInstance.Clock.StartClock(); evt.MapInstance.Broadcast(evt.MapInstance.Clock.GetClock()); } break; case EventActionType.STOPMAPCLOCK: evt.MapInstance.Clock.StopClock(); evt.MapInstance.Broadcast(evt.MapInstance.Clock.GetClock()); break; case EventActionType.SPAWNPORTAL: evt.MapInstance.CreatePortal((Portal)evt.Parameter); break; case EventActionType.REFRESHMAPITEMS: evt.MapInstance.MapClear(); break; case EventActionType.NPCSEFFECTCHANGESTATE: evt.MapInstance.Npcs.ForEach(s => s.EffectActivated = (bool)evt.Parameter); break; case EventActionType.CHANGEPORTALTYPE: Tuple <int, PortalType> param = (Tuple <int, PortalType>)evt.Parameter; Portal portal = evt.MapInstance.Portals.FirstOrDefault(s => s.PortalId == param.Item1); if (portal != null) { portal.Type = (short)param.Item2; } break; case EventActionType.CHANGEDROPRATE: evt.MapInstance.DropRate = (int)evt.Parameter; break; case EventActionType.CHANGEXPRATE: evt.MapInstance.XpRate = (int)evt.Parameter; break; case EventActionType.DISPOSEMAP: evt.MapInstance.Dispose(); break; case EventActionType.SPAWNBUTTON: evt.MapInstance.SpawnButton((MapButton)evt.Parameter); break; case EventActionType.UNSPAWNMONSTERS: evt.MapInstance.DespawnMonster((int)evt.Parameter); break; case EventActionType.SPAWNMONSTERS: evt.MapInstance.SummonMonsters(((ConcurrentBag <MonsterToSummon>)evt.Parameter).ToList()); break; case EventActionType.REFRESHRAIDGOAL: ClientSession cl = evt.MapInstance.Sessions.FirstOrDefault(); if (cl?.Character != null) { ServerManager.Instance.Broadcast(cl, cl.Character?.Group?.GeneraterRaidmbf(), ReceiverType.Group); ServerManager.Instance.Broadcast(cl, UserInterfaceHelper.Instance.GenerateMsg(Language.Instance.GetMessageFromKey("NEW_MISSION"), 0), ReceiverType.Group); } break; case EventActionType.SPAWNNPCS: evt.MapInstance.SummonNpcs((List <NpcToSummon>)evt.Parameter); break; case EventActionType.DROPITEMS: evt.MapInstance.DropItems((List <Tuple <short, int, short, short> >)evt.Parameter); break; case EventActionType.THROWITEMS: Tuple <int, short, byte, int, int> parameters = (Tuple <int, short, byte, int, int>)evt.Parameter; if (monster != null) { parameters = new Tuple <int, short, byte, int, int>(monster.MapMonsterId, parameters.Item2, parameters.Item3, parameters.Item4, parameters.Item5); } evt.MapInstance.ThrowItems(parameters); break; case EventActionType.SPAWNONLASTENTRY: Character lastincharacter = evt.MapInstance.Sessions.OrderByDescending(s => s.RegisterTime).FirstOrDefault()?.Character; List <MonsterToSummon> summonParameters = new List <MonsterToSummon>(); MapCell hornSpawn = new MapCell { X = lastincharacter?.PositionX ?? 154, Y = lastincharacter?.PositionY ?? 140 }; long hornTarget = lastincharacter?.CharacterId ?? -1; summonParameters.Add(new MonsterToSummon(Convert.ToInt16(evt.Parameter), hornSpawn, hornTarget, true)); evt.MapInstance.SummonMonsters(summonParameters); break; #endregion } }
private void NpcLife() { double time = (DateTime.Now - LastEffect).TotalMilliseconds; if (time > EffectDelay) { if (IsMate || IsProtected) { MapInstance.Broadcast(GenerateEff(825), MapX, MapY); } if (Effect > 0 && EffectActivated) { MapInstance.Broadcast(GenerateEff(Effect), MapX, MapY); } LastEffect = DateTime.Now; } time = (DateTime.Now - LastMove).TotalMilliseconds; if (IsMoving && Npc.Speed > 0 && time > _movetime) { _movetime = ServerManager.Instance.RandomNumber(500, 3000); byte point = (byte)ServerManager.Instance.RandomNumber(2, 4); byte fpoint = (byte)ServerManager.Instance.RandomNumber(0, 2); byte xpoint = (byte)ServerManager.Instance.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, GenerateMv2(), ReceiverType.All, xCoordinate: mapX, yCoordinate: mapY)); } } if (Target == -1) { if (IsHostile && Shop == null) { MapMonster monster = MapInstance.Monsters.FirstOrDefault(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.FirstOrDefault(s => s.MapMonsterId == Target); if (monster == null || monster.CurrentHp < 1) { Target = -1; return; } NpcMonsterSkill npcMonsterSkill = null; if (ServerManager.Instance.RandomNumber(0, 10) > 8) { npcMonsterSkill = Npc.Skills.Where(s => (DateTime.Now - s.LastSkillUse).TotalMilliseconds >= 100 * s.Skill.Cooldown).OrderBy(rnd => _random.Next()).FirstOrDefault(); } const short damage = 100; 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.Any() || npcMonsterSkill != null) { if (npcMonsterSkill != null) { npcMonsterSkill.LastSkillUse = DateTime.Now; MapInstance.Broadcast($"ct 2 {MapNpcId} 3 {Target} {npcMonsterSkill.Skill.CastAnimation} {npcMonsterSkill.Skill.CastEffect} {npcMonsterSkill.Skill.SkillVNum}"); } if (npcMonsterSkill != null && npcMonsterSkill.Skill.CastEffect != 0) { MapInstance.Broadcast(GenerateEff(Effect)); } monster.CurrentHp -= damage; MapInstance.Broadcast(npcMonsterSkill != null ? $"su 2 {MapNpcId} 3 {Target} {npcMonsterSkill.SkillVNum} {npcMonsterSkill.Skill.Cooldown} {npcMonsterSkill.Skill.AttackAnimation} {npcMonsterSkill.Skill.Effect} 0 0 {(monster.CurrentHp > 0 ? 1 : 0)} {(int)((double)monster.CurrentHp / monster.Monster.MaxHP * 100)} {damage} 0 0" : $"su 2 {MapNpcId} 3 {Target} 0 {Npc.BasicCooldown} 11 {Npc.BasicSkill} 0 0 {(monster.CurrentHp > 0 ? 1 : 0)} {(int)((double)monster.CurrentHp / monster.Monster.MaxHP * 100)} {damage} 0 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; if (!Path.Any() && distance > 1 && distance < maxDistance) { short xoffset = (short)ServerManager.Instance.RandomNumber(-1, 1); short yoffset = (short)ServerManager.Instance.RandomNumber(-1, 1); //go to monster Path = BestFirstSearch.FindPath(new GridPos { X = MapX, Y = MapY }, new GridPos { X = (short)(monster.MapX + xoffset), Y = (short)(monster.MapY + yoffset) }, MapInstance.Map.Grid); } if (DateTime.Now > LastMove && Npc.Speed > 0 && Path.Any()) { int maxindex = Path.Count > Npc.Speed / 2 && Npc.Speed > 1 ? Npc.Speed / 2 : Path.Count; maxindex = maxindex < 1 ? 1 : maxindex; short mapX = (short)Path.ElementAt(maxindex - 1).X; short mapY = (short)Path.ElementAt(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, $"mv 2 {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 > Path.Count ? Path.Count : 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.Instance.RandomNumber(500, 3000); byte point = (byte)ServerManager.Instance.RandomNumber(2, 4); byte fpoint = (byte)ServerManager.Instance.RandomNumber(0, 2); byte xpoint = (byte)ServerManager.Instance.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.Instance.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); 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.Instance.RandomNumber(-1, 1); short yoffset = (short)ServerManager.Instance.RandomNumber(-1, 1); //go to monster Path = BestFirstSearch.FindPath(new GridPos { X = MapX, Y = MapY }, new GridPos { X = (short)(monster.MapX + xoffset), Y = (short)(monster.MapY + yoffset) }, MapInstance.Map.Grid); 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> /// Run Event /// </summary> /// <param name="evt">Event Container</param> /// <param name="session">Character Session that run the event</param> /// <param name="monster">Monster that run the event</param> public void RunEvent(EventContainer evt, ClientSession session = null, MapMonster monster = null) { if (session != null) { evt.MapInstance = session.CurrentMapInstance; switch (evt.EventActionType) { #region EventForUser case EventActionType.NPCDIALOG: session.SendPacket(session.Character.GenerateNpcDialog((int)evt.Parameter)); break; case EventActionType.SENDPACKET: session.SendPacket((string)evt.Parameter); break; #endregion } } if (evt.MapInstance == null) { return; } switch (evt.EventActionType) { #region EventForUser case EventActionType.NPCDIALOG: case EventActionType.SENDPACKET: if (session == null) { evt.MapInstance.Sessions.ToList().ForEach(e => { RunEvent(evt, e); }); } break; #endregion #region MapInstanceEvent case EventActionType.REGISTEREVENT: Tuple <string, ConcurrentBag <EventContainer> > even = (Tuple <string, ConcurrentBag <EventContainer> >)evt.Parameter; switch (even.Item1) { case "OnCharacterDiscoveringMap": even.Item2.ToList().ForEach(s => evt.MapInstance.OnCharacterDiscoveringMapEvents.Add( new Tuple <EventContainer, List <long> >(s, new List <long>()))); break; case "OnMoveOnMap": even.Item2.ToList().ForEach(s => evt.MapInstance.OnMoveOnMapEvents.Add(s)); break; case "OnMapClean": even.Item2.ToList().ForEach(s => evt.MapInstance.OnMapClean.Add(s)); break; case "OnLockerOpen": if (evt.MapInstance.MapInstanceType == MapInstanceType.RaidInstance) { even.Item2.ToList().ForEach(s => evt.MapInstance.UnlockEvents.Add(s)); break; } even.Item2.ToList().ForEach(s => evt.MapInstance.InstanceBag.UnlockEvents.Add(s)); break; } break; case EventActionType.REGISTERWAVE: evt.MapInstance.WaveEvents.Add((EventWave)evt.Parameter); break; case EventActionType.SETAREAENTRY: var even2 = (ZoneEvent)evt.Parameter; evt.MapInstance.OnAreaEntryEvents.Add(even2); break; case EventActionType.REMOVEMONSTERLOCKER: session = evt.MapInstance.Sessions.FirstOrDefault(); if (evt.MapInstance.MapInstanceType == MapInstanceType.RaidInstance) { if (evt.MapInstance.MonsterLocker.Current > 0) { evt.MapInstance.MonsterLocker.Current--; } if (evt.MapInstance.MonsterLocker.Current == 0 && evt.MapInstance.ButtonLocker.Current == 0) { foreach (EventContainer s in evt.MapInstance.UnlockEvents) { RunEvent(s); } evt.MapInstance.UnlockEvents.Clear(); } evt.MapInstance.Broadcast(session?.Character?.Group?.GeneraterRaidmbf(evt.MapInstance)); break; } if (evt.MapInstance.InstanceBag.MonsterLocker.Current > 0) { evt.MapInstance.InstanceBag.MonsterLocker.Current--; } if (evt.MapInstance.InstanceBag.MonsterLocker.Current == 0 && evt.MapInstance.InstanceBag.ButtonLocker.Current == 0) { evt.MapInstance.InstanceBag.UnlockEvents.ToList().ForEach(s => RunEvent(s)); evt.MapInstance.InstanceBag.UnlockEvents.Clear(); } break; case EventActionType.REMOVEBUTTONLOCKER: session = evt.MapInstance.Sessions.FirstOrDefault(); if (evt.MapInstance.MapInstanceType == MapInstanceType.RaidInstance) { if (evt.MapInstance.ButtonLocker.Current > 0) { evt.MapInstance.ButtonLocker.Current--; } if (evt.MapInstance.MonsterLocker.Current == 0 && evt.MapInstance.ButtonLocker.Current == 0) { evt.MapInstance.UnlockEvents.ToList().ForEach(s => RunEvent(s)); evt.MapInstance.UnlockEvents.Clear(); } evt.MapInstance.Broadcast(session?.Character?.Group?.GeneraterRaidmbf(evt.MapInstance)); break; } if (evt.MapInstance.InstanceBag.ButtonLocker.Current > 0) { evt.MapInstance.InstanceBag.ButtonLocker.Current--; } if (evt.MapInstance.InstanceBag.MonsterLocker.Current == 0 && evt.MapInstance.InstanceBag.ButtonLocker.Current == 0) { evt.MapInstance.InstanceBag.UnlockEvents.ToList().ForEach(s => RunEvent(s)); evt.MapInstance.InstanceBag.UnlockEvents.Clear(); } break; case EventActionType.EFFECT: short evt3 = (short)evt.Parameter; if (monster != null && (DateTime.Now - monster.LastEffect).TotalSeconds >= 5) { evt.MapInstance.Broadcast(monster.GenerateEff(evt3)); monster.ShowEffect(); } break; case EventActionType.INSTANTBATLLEREWARDS: RunEvent(new EventContainer(evt.MapInstance, EventActionType.SPAWNPORTAL, new Portal { SourceX = 47, SourceY = 33, DestinationMapId = 1 })); evt.MapInstance.Broadcast( UserInterfaceHelper.Instance.GenerateMsg( Language.Instance.GetMessageFromKey("INSTANTBATTLE_SUCCEEDED"), 0)); Parallel.ForEach(evt.MapInstance.Sessions.Where(s => s.Character != null), cli => { cli.Character.GetReput(cli.Character.Level * 50, true); cli.Character.GetGold(cli.Character.Level * 1000); cli.Character.SpAdditionPoint += cli.Character.Level * 100; cli.Character.SpAdditionPoint = cli.Character.SpAdditionPoint > 1000000 ? 1000000 : cli.Character.SpAdditionPoint; cli.SendPacket(cli.Character.GenerateSpPoint()); cli.SendPacket(cli.Character.GenerateGold()); cli.SendPacket(cli.Character.GenerateSay( string.Format(Language.Instance.GetMessageFromKey("WIN_SP_POINT"), cli.Character.Level * 100), 10)); }); break; case EventActionType.CONTROLEMONSTERINRANGE: if (monster != null) { Tuple <short, byte, ConcurrentBag <EventContainer> > evnt = (Tuple <short, byte, ConcurrentBag <EventContainer> >)evt.Parameter; List <MapMonster> mapMonsters = evt.MapInstance.GetListMonsterInRange(monster.MapX, monster.MapY, evnt.Item2); if (evnt.Item1 != 0) { mapMonsters.RemoveAll(s => s.MonsterVNum != evnt.Item1); } mapMonsters.ForEach(s => evnt.Item3.ToList().ForEach(e => RunEvent(e, monster: s))); } break; case EventActionType.ONTARGET: if (monster?.MoveEvent != null && monster.MoveEvent.InZone(monster.MapX, monster.MapY)) { monster.MoveEvent = null; monster.Path = null; foreach (EventContainer s in (ConcurrentBag <EventContainer>)evt.Parameter) { RunEvent(s, monster: monster); } } break; case EventActionType.MOVE: var evt4 = (ZoneEvent)evt.Parameter; if (monster != null) { monster.MoveEvent = evt4; monster.Path = BestFirstSearch.FindPath(new Node { X = monster.MapX, Y = monster.MapY }, new Node { X = evt4.X, Y = evt4.Y }, evt.MapInstance?.Map.Grid); } break; case EventActionType.CLOCK: evt.MapInstance.InstanceBag.Clock.BasesSecondRemaining = Convert.ToInt32(evt.Parameter); evt.MapInstance.InstanceBag.Clock.DeciSecondRemaining = Convert.ToInt32(evt.Parameter); break; case EventActionType.SETMONSTERLOCKERS: if (evt.MapInstance.MapInstanceType == MapInstanceType.RaidInstance) { evt.MapInstance.MonsterLocker.Current = Convert.ToByte(evt.Parameter); evt.MapInstance.MonsterLocker.Initial = Convert.ToByte(evt.Parameter); break; } evt.MapInstance.InstanceBag.MonsterLocker.Current = Convert.ToByte(evt.Parameter); evt.MapInstance.InstanceBag.MonsterLocker.Initial = Convert.ToByte(evt.Parameter); break; case EventActionType.SETBUTTONLOCKERS: if (evt.MapInstance.MapInstanceType == MapInstanceType.RaidInstance) { evt.MapInstance.ButtonLocker.Current = Convert.ToByte(evt.Parameter); evt.MapInstance.ButtonLocker.Initial = Convert.ToByte(evt.Parameter); break; } evt.MapInstance.InstanceBag.ButtonLocker.Current = Convert.ToByte(evt.Parameter); evt.MapInstance.InstanceBag.ButtonLocker.Initial = Convert.ToByte(evt.Parameter); break; case EventActionType.SCRIPTEND: ClientSession client = evt.MapInstance.Sessions.FirstOrDefault(); if (client == null) { return; } switch (evt.MapInstance.MapInstanceType) { case MapInstanceType.TimeSpaceInstance: evt.MapInstance.InstanceBag.EndState = (byte)evt.Parameter; Guid mapInstanceId = ServerManager.Instance.GetBaseMapInstanceIdByMapId(client.Character.MapId); MapInstance map = ServerManager.Instance.GetMapInstance(mapInstanceId); ScriptedInstance si = map?.ScriptedInstances?.FirstOrDefault(s => s.PositionX == client.Character.MapX && s.PositionY == client.Character.MapY); if (si == null) { return; } byte penalty = (byte)(client.Character.Level - si.LevelMinimum > 50 ? 100 : (client.Character.Level - si.LevelMinimum) * 2); if (penalty > 0) { client.SendPacket(client.Character.GenerateSay( string.Format(Language.Instance.GetMessageFromKey("TS_PENALTY"), penalty), 10)); } int point = evt.MapInstance.InstanceBag.Point * (100 - penalty) / 100; string perfection = $"{(evt.MapInstance.InstanceBag.MonstersKilled >= si.MonsterAmount ? 1 : 0)}{(evt.MapInstance.InstanceBag.NpcsKilled == 0 ? 1 : 0)}{(evt.MapInstance.InstanceBag.RoomsVisited >= si.RoomAmount ? 1 : 0)}"; evt.MapInstance.Broadcast( $"score {evt.MapInstance.InstanceBag.EndState} {point} 27 47 18 {si.DrawItems.Count} {evt.MapInstance.InstanceBag.MonstersKilled} {si.NpcAmount - evt.MapInstance.InstanceBag.NpcsKilled} {evt.MapInstance.InstanceBag.RoomsVisited} {perfection} 1 1"); break; case MapInstanceType.RaidInstance: evt.MapInstance.InstanceBag.EndState = (byte)evt.Parameter; if (client.Character?.Family?.Act4Raid?.Maps?.FirstOrDefault(m => m != client.Character?.Family?.Act4Raid?.FirstMap) == evt.MapInstance) // Act 4 raids { ScriptedInstance instance = client.Character?.Family?.Act4Raid; if (instance?.FirstMap == null) { return; } Instance.RunEvent(new EventContainer(instance.FirstMap, EventActionType.REMOVEPORTAL, instance.FirstMap.Portals.FirstOrDefault(port => port.DestinationMapInstanceId == client.CurrentMapInstance.MapInstanceId))); Instance.ScheduleEvent(TimeSpan.FromSeconds(5), new EventContainer(evt.MapInstance, EventActionType.SENDPACKET, UserInterfaceHelper.Instance.GenerateMsg( string.Format(Language.Instance.GetMessageFromKey("TELEPORTED_IN"), 10), 0))); foreach (ClientSession cli in evt.MapInstance.Sessions) { if (DaoFactory.RaidLogDao.LoadByFamilyId(cli.Character.Family.FamilyId).Any(s => s.RaidId == instance.Id && s.Time.AddHours(24) <= DateTime.Now)) { // Raid has not been done in the last 24 hours cli.Character.GenerateFamilyXp(instance.Fxp / evt.MapInstance.Sessions.Count()); } else { // Raid has already been done in the last 24 hours cli.Character.GenerateFamilyXp( instance.Fxp / 5 / evt.MapInstance.Sessions.Count()); } cli.SendPacket(cli.Character.GenerateSay( string.Format(Language.Instance.GetMessageFromKey("FXP_INCREASE"), instance.Fxp), 11)); cli.Character.IncrementQuests(QuestType.WinRaid, instance.Id); if (evt.MapInstance.Sessions.Count(s => s.IpAddress.Equals(cli.IpAddress)) > 2 || instance.GiftItems == null) { continue; } foreach (Gift gift in instance.GiftItems) { sbyte rare = (sbyte)(gift.IsRandomRare ? ServerManager.Instance.RandomNumber() : 0); if (rare > 90) { rare = 7; } else if (rare > 80) { rare = 6; } else { rare = (sbyte)(gift.IsRandomRare ? ServerManager.Instance.RandomNumber(1, 6) : 0); } if (cli.Character.Level >= instance.LevelMinimum) { cli.Character.GiftAdd(gift.VNum, gift.Amount, gift.Design, rare: rare); } } } LogHelper.Instance.InsertFamilyRaidLog( evt.MapInstance.Sessions.FirstOrDefault(s => s.Character.Family != null).Character .Family.FamilyId, instance.Id, DateTime.Now); Observable.Timer(TimeSpan.FromSeconds(15)).Subscribe(s => { evt.MapInstance.Sessions.ToList().ForEach(cli => ServerManager.Instance.ChangeMapInstance(cli.Character.CharacterId, instance.FirstMap.MapInstanceId, instance.StartX, instance.StartY)); }); return; } // Raids Group grp = client.Character?.Group; if (grp == null) { return; } if (evt.MapInstance.InstanceBag.EndState == 1 && evt.MapInstance.Monsters.Any(s => s.IsBoss && !s.IsAlive)) { foreach (ClientSession sess in grp.Characters.Where(s => s.CurrentMapInstance?.Monsters.Any(e => e.IsBoss) == true)) { // TODO REMOTE THAT FOR PUBLIC RELEASE if (grp.Characters.Count(s => s.IpAddress.Equals(sess.IpAddress)) > 2 || grp.Raid?.GiftItems == null) { continue; } if (grp.Raid.Reputation > 0 && sess.Character.Level > grp.Raid.LevelMinimum) { sess.Character.GetReput(grp.Raid.Reputation, true); } sess.Character.Dignity = sess.Character.Dignity < 0 ? sess.Character.Dignity + 100 : 100; if (sess.Character.Level > grp.Raid.LevelMaximum) { sess.Character.GiftAdd(2320, 1); // RAID CERTIFICATE continue; } if (grp.Raid?.GiftItems == null) { continue; } foreach (Gift gift in grp.Raid.GiftItems) { sbyte rare; if (gift.IsHeroic) { rare = (sbyte)(gift.IsRandomRare ? ServerManager.Instance.RandomNumber(-2, 9) : 0); } else { rare = (sbyte)(gift.IsRandomRare ? ServerManager.Instance.RandomNumber(-2, 8) : 0); } if (sess.Character.Level >= grp.Raid.LevelMinimum) { sess.Character.GiftAdd(gift.VNum, gift.Amount, gift.Design, rare: rare); } } if (DaoFactory.RaidLogDao.LoadByCharacterId(sess.Character.CharacterId).Any(s => s.RaidId == grp.Raid.Id && s.Time.AddHours(24) >= DateTime.Now) || sess.Character.Family == null) { continue; } LogHelper.Instance.InsertRaidLog(sess.Character.CharacterId, grp.Raid.Id, DateTime.Now); sess.Character.GenerateFamilyXp(grp.Raid.Fxp); sess.SendPacket(sess.Character.GenerateSay( string.Format(Language.Instance.GetMessageFromKey("FXP_INCREASE"), grp.Raid.Fxp), 11)); } // Remove monster when raid is over evt.MapInstance.Monsters.Where(s => !s.IsBoss).ToList() .ForEach(m => evt.MapInstance.DespawnMonster(m)); evt.MapInstance.WaveEvents.Clear(); ServerManager.Instance.Broadcast(UserInterfaceHelper.Instance.GenerateMsg( string.Format(Language.Instance.GetMessageFromKey("RAID_SUCCEED"), grp.Raid?.Label, grp.Characters.ElementAt(0).Character.Name), 0)); } Observable.Timer(TimeSpan.FromSeconds(evt.MapInstance.InstanceBag.EndState == 1 ? 30 : 0)) .Subscribe(obj => { ClientSession[] grpmembers = new ClientSession[40]; grp.Characters.ToList().CopyTo(grpmembers); foreach (ClientSession targetSession in grpmembers) { if (targetSession == null) { continue; } if (targetSession.Character.Hp <= 0) { targetSession.Character.Hp = 1; targetSession.Character.Mp = 1; } targetSession.SendPacket( targetSession.Character.GenerateRaidBf(evt.MapInstance.InstanceBag .EndState)); targetSession.SendPacket(targetSession.Character.GenerateRaid(1, true)); targetSession.SendPacket(targetSession.Character.GenerateRaid(2, true)); grp.LeaveGroup(targetSession); } ServerManager.Instance.GroupList.RemoveAll(s => s.GroupId == grp.GroupId); ServerManager.Instance._groups.TryRemove(grp.GroupId, out Group _); grp.Raid.MapInstanceDictionary.Values.ToList().ForEach(m => m.Dispose()); }); break; case MapInstanceType.CaligorInstance: FactionType winningFaction = Caligor.AngelDamage > Caligor.DemonDamage ? FactionType.Angel : FactionType.Demon; foreach (ClientSession player in evt.MapInstance.Sessions) { if (player == null) { continue; } if (Caligor.RaidTime > 2400) { player.Character.GiftAdd( player.Character.Faction == winningFaction ? (short)5960 : (short)5961, 1); } else { player.Character.GiftAdd( player.Character.Faction == winningFaction ? (short)5961 : (short)5958, 1); } player.Character.GiftAdd(5959, 1); player.Character.GenerateFamilyXp(500); } break; } break; case EventActionType.MAPCLOCK: evt.MapInstance.Clock.BasesSecondRemaining = Convert.ToInt32(evt.Parameter); evt.MapInstance.Clock.DeciSecondRemaining = Convert.ToInt32(evt.Parameter); break; case EventActionType.STARTCLOCK: Tuple <ConcurrentBag <EventContainer>, ConcurrentBag <EventContainer> > eve = (Tuple <ConcurrentBag <EventContainer>, ConcurrentBag <EventContainer> >)evt.Parameter; if (eve != null) { evt.MapInstance.InstanceBag.Clock.StopEvents = eve.Item2.ToList(); evt.MapInstance.InstanceBag.Clock.TimeoutEvents = eve.Item1.ToList(); evt.MapInstance.InstanceBag.Clock.StartClock(); evt.MapInstance.Broadcast(evt.MapInstance.InstanceBag.Clock.GetClock()); } break; case EventActionType.TELEPORT: Tuple <short, short, short, short> tp = (Tuple <short, short, short, short>)evt.Parameter; List <Character> characters = evt.MapInstance.GetCharactersInRange(tp.Item1, tp.Item2, 5).ToList(); characters.ForEach(s => { s.PositionX = tp.Item3; s.PositionY = tp.Item4; evt.MapInstance?.Broadcast(s.Session, s.GenerateTp(), ReceiverType.Group); }); break; case EventActionType.STOPCLOCK: evt.MapInstance.InstanceBag.Clock.StopClock(); evt.MapInstance.Broadcast(evt.MapInstance.InstanceBag.Clock.GetClock()); break; case EventActionType.STARTMAPCLOCK: eve = (Tuple <ConcurrentBag <EventContainer>, ConcurrentBag <EventContainer> >)evt.Parameter; if (eve != null) { evt.MapInstance.Clock.StopEvents = eve.Item2.ToList(); evt.MapInstance.Clock.TimeoutEvents = eve.Item1.ToList(); evt.MapInstance.Clock.StartClock(); evt.MapInstance.Broadcast(evt.MapInstance.Clock.GetClock()); } break; case EventActionType.STOPMAPCLOCK: evt.MapInstance.Clock.StopClock(); evt.MapInstance.Broadcast(evt.MapInstance.Clock.GetClock()); break; case EventActionType.SPAWNPORTAL: evt.MapInstance.CreatePortal((Portal)evt.Parameter); break; case EventActionType.REFRESHMAPITEMS: evt.MapInstance.MapClear(); break; case EventActionType.NPCSEFFECTCHANGESTATE: evt.MapInstance.Npcs.ForEach(s => s.EffectActivated = (bool)evt.Parameter); break; case EventActionType.CHANGEPORTALTYPE: Tuple <int, PortalType> param = (Tuple <int, PortalType>)evt.Parameter; Portal portal = evt.MapInstance.Portals.FirstOrDefault(s => s.PortalId == param.Item1); if (portal != null) { portal.Type = (short)param.Item2; } break; case EventActionType.CHANGEDROPRATE: evt.MapInstance.DropRate = (int)evt.Parameter; break; case EventActionType.CHANGEXPRATE: evt.MapInstance.XpRate = (int)evt.Parameter; break; case EventActionType.DISPOSEMAP: evt.MapInstance.Dispose(); break; case EventActionType.SPAWNBUTTON: evt.MapInstance.SpawnButton((MapButton)evt.Parameter); break; case EventActionType.UNSPAWNMONSTERS: evt.MapInstance.DespawnMonster((int)evt.Parameter); break; case EventActionType.SPAWNMONSTERS: evt.MapInstance.SummonMonsters(((ConcurrentBag <ToSummon>)evt.Parameter).ToList()); break; case EventActionType.REFRESHRAIDGOAL: ClientSession cl = evt.MapInstance.Sessions.FirstOrDefault(); if (cl?.Character != null) { evt.MapInstance.Broadcast(cl.Character?.Group?.GeneraterRaidmbf(evt.MapInstance)); ServerManager.Instance.Broadcast(cl, UserInterfaceHelper.Instance.GenerateMsg(Language.Instance.GetMessageFromKey("NEW_MISSION"), 0), ReceiverType.Group); } break; case EventActionType.SPAWNNPCS: evt.MapInstance.SummonNpcs((List <ToSummon>)evt.Parameter); break; case EventActionType.DROPITEMS: evt.MapInstance.DropItems((List <Tuple <short, int, short, short> >)evt.Parameter); break; case EventActionType.THROWITEMS: Tuple <int, short, byte, int, int> parameters = (Tuple <int, short, byte, int, int>)evt.Parameter; if (monster != null) { parameters = new Tuple <int, short, byte, int, int>(monster.MapMonsterId, parameters.Item2, parameters.Item3, parameters.Item4, parameters.Item5); } evt.MapInstance.ThrowItems(parameters); break; case EventActionType.SPAWNONLASTENTRY: Character lastincharacter = evt.MapInstance.Sessions.OrderByDescending(s => s.RegisterTime) .FirstOrDefault()?.Character; List <ToSummon> summonParameters = new List <ToSummon>(); var hornSpawn = new MapCell { X = lastincharacter?.PositionX ?? 154, Y = lastincharacter?.PositionY ?? 140 }; summonParameters.Add(new ToSummon(Convert.ToInt16(evt.Parameter), hornSpawn, lastincharacter, true)); evt.MapInstance.SummonMonsters(summonParameters); break; case EventActionType.REMOVEPORTAL: Portal portalToRemove = evt.Parameter is Portal p ? evt.MapInstance.Portals.FirstOrDefault(s => s == p) : evt.MapInstance.Portals.FirstOrDefault(s => s.PortalId == (int)evt.Parameter); if (portalToRemove == null) { return; } evt.MapInstance.Portals.Remove(portalToRemove); evt.MapInstance.MapClear(); break; case EventActionType.ACT4RAIDEND: // tp // tp X // tp Y Tuple <MapInstance, short, short> endParameters = (Tuple <MapInstance, short, short>)evt.Parameter; Observable.Timer(TimeSpan.FromSeconds(5)).Subscribe(a => { evt.MapInstance.Broadcast( $"{UserInterfaceHelper.Instance.GenerateMsg(string.Format(Language.Instance.GetMessageFromKey("TELEPORTED_IN"), 10), 0)}"); Observable.Timer(TimeSpan.FromSeconds(10)).Subscribe(s => { evt.MapInstance.Sessions.ToList().ForEach(cli => ServerManager.Instance.ChangeMapInstance(cli.Character.CharacterId, endParameters.Item1.MapInstanceId, endParameters.Item2, endParameters.Item3)); }); }); break; case EventActionType.CLEARMAPMONSTERS: evt.MapInstance.Monsters.ForEach(m => evt.MapInstance.DespawnMonster(m)); break; case EventActionType.STARTACT4RAID: Tuple <byte, byte> raidParameters = (Tuple <byte, byte>)evt.Parameter; PercentBar stat = raidParameters.Item2 == (byte)FactionType.Angel ? ServerManager.Instance.Act4AngelStat : ServerManager.Instance.Act4DemonStat; stat.Mode = 3; stat.TotalTime = 3600; Act4Raid.Instance.GenerateRaid(raidParameters.Item1, raidParameters.Item2); switch ((Act4RaidType)raidParameters.Item1) { case Act4RaidType.Morcos: stat.IsMorcos = true; break; case Act4RaidType.Hatus: stat.IsHatus = true; break; case Act4RaidType.Calvina: stat.IsCalvina = true; break; case Act4RaidType.Berios: stat.IsBerios = true; break; } break; case EventActionType.ONTIMEELAPSED: Tuple <int, ConcurrentBag <EventContainer> > timeElapsedEvts = (Tuple <int, ConcurrentBag <EventContainer> >)evt.Parameter; Observable.Timer(TimeSpan.FromSeconds(timeElapsedEvts.Item1)).Subscribe(e => { timeElapsedEvts.Item2.ToList().ForEach(ev => RunEvent(ev)); }); break; #endregion } }
public void RunEvent(EventContainer evt, ClientSession session = null, MapMonster monster = null) { if (evt != null) { if (session != null) { evt.MapInstance = session.CurrentMapInstance; switch (evt.EventActionType) { #region EventForUser case EventActionType.NPCDIALOG: session.SendPacket(session.Character.GenerateNpcDialog((int)evt.Parameter)); break; case EventActionType.SENDPACKET: session.SendPacket((string)evt.Parameter); break; #endregion } } if (evt.MapInstance != null) { switch (evt.EventActionType) { #region EventForUser case EventActionType.NPCDIALOG: case EventActionType.SENDPACKET: if (session == null) { evt.MapInstance.Sessions.ToList().ForEach(e => RunEvent(evt, e)); } break; #endregion #region MapInstanceEvent case EventActionType.REGISTEREVENT: Tuple <string, List <EventContainer> > even = (Tuple <string, List <EventContainer> >)evt.Parameter; switch (even.Item1) { case "OnCharacterDiscoveringMap": even.Item2.ForEach(s => evt.MapInstance.OnCharacterDiscoveringMapEvents.Add(new Tuple <EventContainer, List <long> >(s, new List <long>()))); break; case "OnMoveOnMap": evt.MapInstance.OnMoveOnMapEvents.GetAllItems().AddRange(even.Item2); break; case "OnMapClean": evt.MapInstance.OnMapClean.AddRange(even.Item2); break; case "OnLockerOpen": evt.MapInstance.InstanceBag.UnlockEvents.AddRange(even.Item2); break; } break; case EventActionType.REGISTERWAVE: evt.MapInstance.WaveEvents.Add((EventWave)evt.Parameter); break; case EventActionType.SETAREAENTRY: ZoneEvent even2 = (ZoneEvent)evt.Parameter; evt.MapInstance.OnAreaEntryEvents.Add(even2); break; case EventActionType.REMOVEMONSTERLOCKER: EventContainer evt2 = (EventContainer)evt.Parameter; if (evt.MapInstance.InstanceBag.MonsterLocker.Current > 0) { evt.MapInstance.InstanceBag.MonsterLocker.Current--; } if (evt.MapInstance.InstanceBag.MonsterLocker.Current == 0 && evt.MapInstance.InstanceBag.ButtonLocker.Current == 0) { evt.MapInstance.InstanceBag.UnlockEvents.ForEach(s => RunEvent(s)); evt.MapInstance.InstanceBag.UnlockEvents.RemoveAll(s => s != null); } break; case EventActionType.REMOVEBUTTONLOCKER: evt2 = (EventContainer)evt.Parameter; if (evt.MapInstance.InstanceBag.ButtonLocker.Current > 0) { evt.MapInstance.InstanceBag.ButtonLocker.Current--; } if (evt.MapInstance.InstanceBag.MonsterLocker.Current == 0 && evt.MapInstance.InstanceBag.ButtonLocker.Current == 0) { evt.MapInstance.InstanceBag.UnlockEvents.ForEach(s => RunEvent(s)); evt.MapInstance.InstanceBag.UnlockEvents.RemoveAll(s => s != null); } break; case EventActionType.EFFECT: short evt3 = (short)evt.Parameter; if (monster != null) { monster.LastEffect = DateTime.Now; evt.MapInstance.Broadcast(StaticPacketHelper.GenerateEff(UserType.Monster, monster.MapMonsterId, evt3)); } break; case EventActionType.CONTROLEMONSTERINRANGE: if (monster != null) { Tuple <short, byte, List <EventContainer> > evnt = (Tuple <short, byte, List <EventContainer> >)evt.Parameter; List <MapMonster> MapMonsters = evt.MapInstance.GetListMonsterInRange(monster.MapX, monster.MapY, evnt.Item2); if (evnt.Item1 != 0) { MapMonsters.RemoveAll(s => s.MonsterVNum != evnt.Item1); } MapMonsters.ForEach(s => evnt.Item3.ForEach(e => RunEvent(e, monster: s))); } break; case EventActionType.ONTARGET: if (monster.MoveEvent?.InZone(monster.MapX, monster.MapY) == true) { monster.MoveEvent = null; monster.Path = new List <Node>(); ((List <EventContainer>)evt.Parameter).ForEach(s => RunEvent(s, monster: monster)); } break; case EventActionType.MOVE: ZoneEvent evt4 = (ZoneEvent)evt.Parameter; if (monster != null) { monster.MoveEvent = evt4; monster.Path = BestFirstSearch.FindPath(new Node { X = monster.MapX, Y = monster.MapY }, new Node { X = evt4.X, Y = evt4.Y }, evt.MapInstance?.Map.Grid); } break; case EventActionType.CLOCK: evt.MapInstance.InstanceBag.Clock.BasesSecondRemaining = Convert.ToInt32(evt.Parameter); evt.MapInstance.InstanceBag.Clock.DeciSecondRemaining = Convert.ToInt32(evt.Parameter); break; case EventActionType.SETMONSTERLOCKERS: evt.MapInstance.InstanceBag.MonsterLocker.Current = Convert.ToByte(evt.Parameter); evt.MapInstance.InstanceBag.MonsterLocker.Initial = Convert.ToByte(evt.Parameter); break; case EventActionType.SETBUTTONLOCKERS: evt.MapInstance.InstanceBag.ButtonLocker.Current = Convert.ToByte(evt.Parameter); evt.MapInstance.InstanceBag.ButtonLocker.Initial = Convert.ToByte(evt.Parameter); break; case EventActionType.SCRIPTEND: switch (evt.MapInstance.MapInstanceType) { case MapInstanceType.TimeSpaceInstance: evt.MapInstance.InstanceBag.EndState = (byte)evt.Parameter; ClientSession client = evt.MapInstance.Sessions.FirstOrDefault(); if (client != null) { Guid MapInstanceId = ServerManager.Instance.GetBaseMapInstanceIdByMapId(client.Character.MapId); MapInstance map = ServerManager.Instance.GetMapInstance(MapInstanceId); ScriptedInstance si = map.ScriptedInstances.Find(s => s.PositionX == client.Character.MapX && s.PositionY == client.Character.MapY); byte penalty = 0; if (penalty > (client.Character.Level - si.LevelMinimum) * 2) { penalty = penalty > 100 ? (byte)100 : penalty; client.SendPacket(client.Character.GenerateSay(string.Format(Language.Instance.GetMessageFromKey("TS_PENALTY"), penalty), 10)); } int point = evt.MapInstance.InstanceBag.Point * (100 - penalty) / 100; string perfection = string.Empty; perfection += evt.MapInstance.InstanceBag.MonstersKilled >= si.MonsterAmount ? 1 : 0; perfection += evt.MapInstance.InstanceBag.NpcsKilled == 0 ? 1 : 0; perfection += evt.MapInstance.InstanceBag.RoomsVisited >= si.RoomAmount ? 1 : 0; evt.MapInstance.Broadcast($"score {evt.MapInstance.InstanceBag.EndState} {point} 27 47 18 {si.DrawItems.Count} {evt.MapInstance.InstanceBag.MonstersKilled} {si.NpcAmount - evt.MapInstance.InstanceBag.NpcsKilled} {evt.MapInstance.InstanceBag.RoomsVisited} {perfection} 1 1"); } break; case MapInstanceType.RaidInstance: evt.MapInstance.InstanceBag.EndState = (byte)evt.Parameter; client = evt.MapInstance.Sessions.FirstOrDefault(); if (client != null) { Group grp = client?.Character?.Group; if (grp == null) { return; } if (evt.MapInstance.InstanceBag.EndState == 1 && evt.MapInstance.Monsters.Any(s => s.IsBoss)) { foreach (ClientSession sess in grp.Characters.Where(s => s.CurrentMapInstance.Monsters.Any(e => e.IsBoss))) { foreach (Gift gift in grp?.Raid?.GiftItems) { const byte rare = 0; // TODO: add random rarity for some object sess.Character.GiftAdd(gift.VNum, gift.Amount, rare, 0, gift.Design, gift.IsRandomRare); } } foreach (MapMonster mon in evt.MapInstance.Monsters) { mon.CurrentHp = 0; evt.MapInstance.Broadcast(StaticPacketHelper.Out(UserType.Monster, mon.MapMonsterId)); evt.MapInstance.RemoveMonster(mon); } Logger.LogUserEvent("RAID_SUCCESS", grp.Characters.ElementAt(0).Character.Name, $"RaidId: {grp.GroupId}"); ServerManager.Instance.Broadcast(UserInterfaceHelper.Instance.GenerateMsg(string.Format(Language.Instance.GetMessageFromKey("RAID_SUCCEED"), grp?.Raid?.Label, grp.Characters.ElementAt(0).Character.Name), 0)); } Observable.Timer(TimeSpan.FromSeconds(evt.MapInstance.InstanceBag.EndState == 1 ? 30 : 0)).Subscribe(o => { ClientSession[] grpmembers = new ClientSession[40]; grp.Characters.CopyTo(grpmembers); foreach (ClientSession targetSession in grpmembers) { if (targetSession != null) { if (targetSession.Character.Hp <= 0) { targetSession.Character.Hp = 1; targetSession.Character.Mp = 1; } targetSession.SendPacket(targetSession.Character.GenerateRaidBf(evt.MapInstance.InstanceBag.EndState)); targetSession.SendPacket(targetSession.Character.GenerateRaid(1, true)); targetSession.SendPacket(targetSession.Character.GenerateRaid(2, true)); grp.LeaveGroup(targetSession); } } ServerManager.Instance.GroupList.RemoveAll(s => s.GroupId == grp.GroupId); ServerManager.Instance.GroupsThreadSafe.Remove(grp.GroupId); evt.MapInstance.Dispose(); }); } break; case MapInstanceType.Act4Morcos: case MapInstanceType.Act4Hatus: case MapInstanceType.Act4Calvina: case MapInstanceType.Act4Berios: client = evt.MapInstance.Sessions.FirstOrDefault(); if (client != null) { Family fam = evt.MapInstance.Sessions.FirstOrDefault(s => s?.Character?.Family != null)?.Character.Family; if (fam != null) { fam.Act4Raid.Portals.RemoveAll(s => s.DestinationMapInstanceId.Equals(fam.Act4RaidBossMap.MapInstanceId)); short destX = 38; short destY = 179; short rewardVNum = 882; switch (evt.MapInstance.MapInstanceType) { //Morcos is default case MapInstanceType.Act4Hatus: destX = 18; destY = 10; rewardVNum = 185; break; case MapInstanceType.Act4Calvina: destX = 25; destY = 7; rewardVNum = 942; break; case MapInstanceType.Act4Berios: destX = 16; destY = 25; rewardVNum = 999; break; } int count = evt.MapInstance.Sessions.Count(s => s?.Character != null); foreach (ClientSession sess in evt.MapInstance.Sessions) { if (sess?.Character != null) { sess.Character.GiftAdd(rewardVNum, 1, forceRandom: true, minRare: 1, design: 255); sess.Character.GenerateFamilyXp(10000 / count); } } Logger.LogEvent("FAMILYRAID_SUCCESS", $"[fam.Name]FamilyRaidId: {evt.MapInstance.MapInstanceType.ToString()}"); //TODO: Raid Ending Messages, Famlog etc //ServerManager.Instance.Broadcast(UserInterfaceHelper.Instance.GenerateMsg(string.Format(Language.Instance.GetMessageFromKey("FAMILYRAID_SUCCESS"), grp?.Raid?.Label, grp.Characters.ElementAt(0).Character.Name), 0)); Observable.Timer(TimeSpan.FromSeconds(30)).Subscribe(o => { foreach (ClientSession targetSession in evt.MapInstance.Sessions.ToArray()) { if (targetSession != null) { if (targetSession.Character.Hp <= 0) { targetSession.Character.Hp = 1; targetSession.Character.Mp = 1; } ServerManager.Instance.ChangeMapInstance(targetSession.Character.CharacterId, fam.Act4Raid.MapInstanceId, destX, destY); } } evt.MapInstance.Dispose(); }); } } break; } break; case EventActionType.MAPCLOCK: evt.MapInstance.Clock.BasesSecondRemaining = Convert.ToInt32(evt.Parameter); evt.MapInstance.Clock.DeciSecondRemaining = Convert.ToInt32(evt.Parameter); break; case EventActionType.STARTCLOCK: Tuple <List <EventContainer>, List <EventContainer> > eve = (Tuple <List <EventContainer>, List <EventContainer> >)evt.Parameter; evt.MapInstance.InstanceBag.Clock.StopEvents = eve.Item2; evt.MapInstance.InstanceBag.Clock.TimeoutEvents = eve.Item1; evt.MapInstance.InstanceBag.Clock.StartClock(); evt.MapInstance.Broadcast(evt.MapInstance.InstanceBag.Clock.GetClock()); break; case EventActionType.TELEPORT: Tuple <short, short, short, short> tp = (Tuple <short, short, short, short>)evt.Parameter; List <Character> characters = evt.MapInstance.GetCharactersInRange(tp.Item1, tp.Item2, 5).ToList(); characters.ForEach(s => { s.PositionX = tp.Item3; s.PositionY = tp.Item4; evt.MapInstance?.Broadcast(s.Session, s.GenerateTp(), ReceiverType.Group); }); break; case EventActionType.STOPCLOCK: evt.MapInstance.InstanceBag.Clock.StopClock(); evt.MapInstance.Broadcast(evt.MapInstance.InstanceBag.Clock.GetClock()); break; case EventActionType.STARTMAPCLOCK: eve = (Tuple <List <EventContainer>, List <EventContainer> >)evt.Parameter; evt.MapInstance.Clock.StopEvents = eve.Item2; evt.MapInstance.Clock.TimeoutEvents = eve.Item1; evt.MapInstance.Clock.StartClock(); evt.MapInstance.Broadcast(evt.MapInstance.Clock.GetClock()); break; case EventActionType.STOPMAPCLOCK: evt.MapInstance.Clock.StopClock(); evt.MapInstance.Broadcast(evt.MapInstance.Clock.GetClock()); break; case EventActionType.SPAWNPORTAL: evt.MapInstance.CreatePortal((Portal)evt.Parameter); break; case EventActionType.REFRESHMAPITEMS: evt.MapInstance.MapClear(); break; case EventActionType.NPCSEFFECTCHANGESTATE: evt.MapInstance.Npcs.ForEach(s => s.EffectActivated = (bool)evt.Parameter); break; case EventActionType.CHANGEPORTALTYPE: Tuple <int, PortalType> param = (Tuple <int, PortalType>)evt.Parameter; Portal portal = evt.MapInstance.Portals.Find(s => s.PortalId == param.Item1); if (portal != null) { portal.Type = (short)param.Item2; } break; case EventActionType.CHANGEDROPRATE: evt.MapInstance.DropRate = (int)evt.Parameter; break; case EventActionType.CHANGEXPRATE: evt.MapInstance.XpRate = (int)evt.Parameter; break; case EventActionType.DISPOSEMAP: evt.MapInstance.Dispose(); break; case EventActionType.SPAWNBUTTON: evt.MapInstance.SpawnButton((MapButton)evt.Parameter); break; case EventActionType.UNSPAWNMONSTERS: evt.MapInstance.DespawnMonster((int)evt.Parameter); break; case EventActionType.SPAWNMONSTER: evt.MapInstance.SummonMonster((MonsterToSummon)evt.Parameter); break; case EventActionType.SPAWNMONSTERS: evt.MapInstance.SummonMonsters((List <MonsterToSummon>)evt.Parameter); break; case EventActionType.REFRESHRAIDGOAL: ClientSession cl = evt.MapInstance.Sessions.FirstOrDefault(); if (cl?.Character != null) { ServerManager.Instance.Broadcast(cl, cl.Character?.Group?.GeneraterRaidmbf(cl), ReceiverType.Group); ServerManager.Instance.Broadcast(cl, UserInterfaceHelper.Instance.GenerateMsg(Language.Instance.GetMessageFromKey("NEW_MISSION"), 0), ReceiverType.Group); } break; case EventActionType.SPAWNNPC: evt.MapInstance.SummonNpc((NpcToSummon)evt.Parameter); break; case EventActionType.SPAWNNPCS: evt.MapInstance.SummonNpcs((List <NpcToSummon>)evt.Parameter); break; case EventActionType.DROPITEMS: evt.MapInstance.DropItems((List <Tuple <short, int, short, short> >)evt.Parameter); break; case EventActionType.THROWITEMS: Tuple <int, short, byte, int, int> parameters = (Tuple <int, short, byte, int, int>)evt.Parameter; if (monster != null) { parameters = new Tuple <int, short, byte, int, int>(monster.MapMonsterId, parameters.Item2, parameters.Item3, parameters.Item4, parameters.Item5); } evt.MapInstance.ThrowItems(parameters); break; case EventActionType.SPAWNONLASTENTRY: Character lastincharacter = evt.MapInstance.Sessions.OrderByDescending(s => s.RegisterTime).FirstOrDefault()?.Character; List <MonsterToSummon> summonParameters = new List <MonsterToSummon>(); MapCell hornSpawn = new MapCell { X = lastincharacter?.PositionX ?? 154, Y = lastincharacter?.PositionY ?? 140 }; long hornTarget = lastincharacter?.CharacterId ?? -1; summonParameters.Add(new MonsterToSummon(Convert.ToInt16(evt.Parameter), hornSpawn, hornTarget, true)); evt.MapInstance.SummonMonsters(summonParameters); break; #endregion } } } }