public void AddBalloon(IFieldObject <InteractObject> balloon) { State.AddBalloon(balloon); Broadcast(session => { session.Send(InteractObjectPacket.AddAdBallons(balloon)); }); }
public void SetInteractObject(int[] interactObjectIds, byte state, bool arg4, bool arg3) { //This should be correct, but the current way of parsing interactObjects does not comply with triggerScripts. Needs changing. foreach (int interactObjectId in interactObjectIds) { //Field.State.InteractObjects[interactObjectId].Id = state Field.BroadcastPacket(InteractObjectPacket.ActivateInteractObject(interactObjectId)); } }
public void SetInteractObject(int[] interactObjectIds, byte state, bool arg4, bool arg3) { InteractObjectState objectState = (InteractObjectState)state; foreach (int interactObjectId in interactObjectIds) { InteractObject interactObject = Field.State.InteractObjects.Values.FirstOrDefault(x => x.InteractId == interactObjectId); if (interactObject == null) { continue; } interactObject.State = objectState; Field.BroadcastPacket(InteractObjectPacket.Set(interactObject)); } }
public void AddInteractObject(ICollection <IFieldObject <InteractObject> > objects) { foreach (IFieldObject <InteractObject> interactObject in objects) { State.AddInteractObject(interactObject); } if (objects.Count > 0) { Broadcast(session => { session.Send(InteractObjectPacket.AddInteractObjects(objects)); }); } }
public static void HandleInstallBillBoard(GameSession session, PacketReader packet, Item item) { string[] parameters = packet.ReadUnicodeString().Split("'"); string title = parameters[0]; string description = parameters[1]; bool publicHouse = parameters[2].Equals("1"); int balloonUid = GuidGenerator.Int(); string id = "AdBalloon_" + balloonUid.ToString(); AdBalloon balloon = new AdBalloon(id, item.Function.InstallBillboard.InteractId, InteractObjectState.Default, InteractObjectType.AdBalloon, session.FieldPlayer, item.Function.InstallBillboard, title, description, publicHouse); session.FieldManager.State.AddInteractObject(balloon); session.FieldManager.BroadcastPacket(InteractObjectPacket.LoadAdBallon(balloon)); InventoryController.Consume(session, item.Uid, 1); }
private static void HandleInteract(GameSession session, PacketReader packet) { string id = packet.ReadMapleString(); InteractObject interactObject = session.FieldManager.State.InteractObjects[id]; if (interactObject == null) { return; } InteractObjectMetadata metadata = InteractObjectMetadataStorage.GetInteractObjectMetadata(interactObject.InteractId); switch (interactObject.Type) { case InteractObjectType.Binoculars: session.Send(InteractObjectPacket.Use(interactObject)); QuestHelper.UpdateExplorationQuest(session, interactObject.InteractId.ToString(), "interact_object_rep"); break; case InteractObjectType.Ui: session.Send(InteractObjectPacket.Use(interactObject)); break; case InteractObjectType.RankBoard: session.Send(WebOpenPacket.Open(metadata.Web.Url)); break; case InteractObjectType.AdBalloon: session.Send(PlayerHostPacket.AdBalloonWindow((AdBalloon)interactObject)); break; case InteractObjectType.Gathering: GatheringHelper.HandleGathering(session, metadata.Gathering.RecipeId, out int numDrop); session.Send(InteractObjectPacket.Use(interactObject, (short)(numDrop > 0 ? 0 : 1), numDrop)); break; } session.Send(InteractObjectPacket.Interact(interactObject)); }
private static void HandleUse(GameSession session, PacketReader packet) { string uuid = packet.ReadMapleString(); IFieldObject <InteractObject> interactObject = session.FieldManager.State.InteractObjects[uuid]; if (interactObject == null) { return; } MapInteractObject mapObject = MapEntityStorage.GetInteractObject(session.Player.MapId).FirstOrDefault(x => x.Uuid == uuid); int numDrop = 0; switch (interactObject.Value.Type) { case InteractObjectType.Binoculars: QuestHelper.UpdateExplorationQuest(session, mapObject.InteractId.ToString(), "interact_object_rep"); break; case InteractObjectType.Gathering: RecipeMetadata recipe = RecipeMetadataStorage.GetRecipe(mapObject.RecipeId); session.Player.Levels.GainMasteryExp((MasteryType)recipe.MasteryType, 0); long currentMastery = session.Player.Levels.MasteryExp.FirstOrDefault(x => x.Type == (MasteryType)recipe.MasteryType).CurrentExp; if (currentMastery < recipe.RequireMastery) { return; } session.Player.IncrementGatheringCount(mapObject.RecipeId, 0); int numCount = session.Player.GatheringCount[mapObject.RecipeId].Current; List <RecipeItem> items = RecipeMetadataStorage.GetResult(recipe); int masteryDiffFactor = numCount switch { int n when n < recipe.HighPropLimitCount => MasteryFactorMetadataStorage.GetFactor(0), int n when n < recipe.NormalPropLimitCount => MasteryFactorMetadataStorage.GetFactor(1), int n when n < (int)(recipe.NormalPropLimitCount * 1.3) => MasteryFactorMetadataStorage.GetFactor(2), _ => MasteryFactorMetadataStorage.GetFactor(3), }; foreach (RecipeItem item in items) { int prob = RarityChance[item.Rarity] * masteryDiffFactor / 10000; if (RandomProvider.Get().Next(100) >= prob) { continue; } for (int i = 0; i < item.Amount; i++) { session.FieldManager.AddItem(session, new Item(item.Id)); } numDrop += item.Amount; } if (numDrop > 0) { session.Player.IncrementGatheringCount(mapObject.RecipeId, numDrop); session.Player.Levels.GainMasteryExp((MasteryType)recipe.MasteryType, recipe.RewardMastery); } break; case InteractObjectType.AdBalloon: session.Send(PlayerHostPacket.AdBalloonWindow(interactObject)); return; default: break; } session.Send(InteractObjectPacket.UseObject(mapObject, (short)(numDrop > 0 ? 0 : 1), numDrop)); session.Send(InteractObjectPacket.Extra(mapObject)); }
private static void HandleUse(GameSession session, PacketReader packet) { string uuid = packet.ReadMapleString(); MapInteractObject interactObject = MapEntityStorage.GetInteractObject(session.Player.MapId).FirstOrDefault(x => x.Uuid == uuid); int numDrop = 0; if (interactObject == null) { return; } if (interactObject.Type == InteractObjectType.Binoculars) { QuestHelper.UpdateExplorationQuest(session, interactObject.InteractId.ToString(), "interact_object_rep"); } else if (interactObject.Type == InteractObjectType.Gathering) { RecipeMetadata recipe = RecipeMetadataStorage.GetRecipe(interactObject.RecipeId); long requireMastery = int.Parse(recipe.RequireMastery); Enums.MasteryType type = (Enums.MasteryType) int.Parse(recipe.MasteryType); session.Player.Levels.GainMasteryExp(type, 0); long currentMastery = session.Player.Levels.MasteryExp.FirstOrDefault(x => x.Type == type).CurrentExp; if (currentMastery < requireMastery) { return; } session.Player.IncrementGatheringCount(interactObject.RecipeId, 0); int numCount = session.Player.GatheringCount[interactObject.RecipeId].Current; List <RecipeItem> items = RecipeMetadataStorage.GetResult(recipe); Random rand = new Random(); int masteryDiffFactor = numCount switch { int n when n < recipe.HighPropLimitCount => MasteryFactorMetadataStorage.GetFactor(0), int n when n < recipe.NormalPropLimitCount => MasteryFactorMetadataStorage.GetFactor(1), int n when n < (int)(recipe.NormalPropLimitCount * 1.3) => MasteryFactorMetadataStorage.GetFactor(2), _ => MasteryFactorMetadataStorage.GetFactor(3), }; foreach (RecipeItem item in items) { int prob = (int)(RarityChance[item.Rarity] * masteryDiffFactor) / 10000; if (rand.Next(100) >= prob) { continue; } for (int i = 0; i < item.Amount; i++) { session.FieldManager.AddItem(session, new Item(item.Id)); } numDrop += item.Amount; } if (numDrop > 0) { session.Player.IncrementGatheringCount(interactObject.RecipeId, numDrop); session.Player.Levels.GainMasteryExp(type, recipe.RewardMastery); } } session.Send(InteractObjectPacket.UseObject(interactObject, (short)(numDrop > 0 ? 0 : 1), numDrop)); session.Send(InteractObjectPacket.Extra(interactObject)); }
public void AddPlayer(GameSession sender, IFieldObject <Player> player) { Debug.Assert(player.ObjectId > 0, "Player was added to field without initialized objectId."); player.Coord = player.Value.Coord; player.Value.MapId = MapId; // TODO: Determine new coordinates for player as well lock (Sessions) { Sessions.Add(sender); } // TODO: Send the initialization state of the field foreach (IFieldObject <Player> existingPlayer in State.Players.Values) { sender.Send(FieldPacket.AddPlayer(existingPlayer)); sender.Send(FieldObjectPacket.LoadPlayer(existingPlayer)); } State.AddPlayer(player); // Broadcast new player to all players in map Broadcast(session => { session.Send(FieldPacket.AddPlayer(player)); session.Send(FieldObjectPacket.LoadPlayer(player)); }); foreach (IFieldObject <Item> existingItem in State.Items.Values) { sender.Send(FieldPacket.AddItem(existingItem, 123456)); } foreach (IFieldObject <Npc> existingNpc in State.Npcs.Values) { sender.Send(FieldPacket.AddNpc(existingNpc)); sender.Send(FieldObjectPacket.LoadNpc(existingNpc)); } foreach (IFieldObject <Portal> existingPortal in State.Portals.Values) { sender.Send(FieldPacket.AddPortal(existingPortal)); } foreach (IFieldObject <Mob> existingMob in State.Mobs.Values) { sender.Send(FieldPacket.AddMob(existingMob)); sender.Send(FieldObjectPacket.LoadMob(existingMob)); } if (player.Value.MapId == (int)Map.PrivateResidence && !player.Value.IsInDecorPlanner) { // Send function cubes List <Cube> functionCubes = State.Cubes.Values.Where(x => x.Value.PlotNumber == 1 && (x.Value.Item.HousingCategory is ItemHousingCategory.Farming or ItemHousingCategory.Ranching)) .Select(x => x.Value).ToList(); if (functionCubes.Count > 0) { sender.Send(FunctionCubePacket.SendCubes(functionCubes)); } } foreach (IFieldObject <GuideObject> guide in State.Guide.Values) { sender.Send(GuideObjectPacket.Add(guide)); } foreach (IFieldObject <HealingSpot> healingSpot in State.HealingSpots.Values) { sender.Send(RegionSkillPacket.Send(healingSpot.ObjectId, healingSpot.Value.Coord, new SkillCast(70000018, 1, 0, 1))); } foreach (IFieldObject <Instrument> instrument in State.Instruments.Values) { if (instrument.Value.Improvise) { sender.Send(InstrumentPacket.StartImprovise(instrument)); } else { sender.Send(InstrumentPacket.PlayScore(instrument)); } } List <BreakableObject> breakables = new List <BreakableObject>(); breakables.AddRange(State.BreakableActors.Values.ToList()); breakables.AddRange(State.BreakableNifs.Values.ToList()); sender.Send(BreakablePacket.LoadBreakables(breakables)); List <InteractObject> interactObjects = new List <InteractObject>(); interactObjects.AddRange(State.InteractObjects.Values.Where(t => t is not AdBalloon).ToList()); sender.Send(InteractObjectPacket.LoadInteractObject(interactObjects)); List <AdBalloon> adBalloons = new List <AdBalloon>(); adBalloons.AddRange(State.InteractObjects.Values.OfType <AdBalloon>().ToList()); foreach (AdBalloon balloon in adBalloons) { sender.Send(InteractObjectPacket.LoadAdBallon(balloon)); } List <TriggerObject> triggerObjects = new List <TriggerObject>(); triggerObjects.AddRange(State.TriggerMeshes.Values.ToList()); triggerObjects.AddRange(State.TriggerEffects.Values.ToList()); triggerObjects.AddRange(State.TriggerCameras.Values.ToList()); triggerObjects.AddRange(State.TriggerActors.Values.ToList()); triggerObjects.AddRange(State.TriggerCubes.Values.ToList()); triggerObjects.AddRange(State.TriggerLadders.Values.ToList()); triggerObjects.AddRange(State.TriggerRopes.Values.ToList()); triggerObjects.AddRange(State.TriggerSounds.Values.ToList()); sender.Send(TriggerPacket.LoadTriggers(triggerObjects)); if (MapLoopTask == null) { MapLoopTask = StartMapLoop(); //TODO: find a better place to initialise MapLoopTask } }
public void AddPlayer(GameSession sender, IFieldObject <Player> player) { Debug.Assert(player.ObjectId > 0, "Player was added to field without initialized objectId."); player.Coord = player.Value.Coord; player.Value.MapId = MapId; // TODO: Determine new coordinates for player as well lock (Sessions) { Sessions.Add(sender); } // TODO: Send the initialization state of the field foreach (IFieldObject <Player> existingPlayer in State.Players.Values) { sender.Send(FieldPacket.AddPlayer(existingPlayer)); sender.Send(FieldObjectPacket.LoadPlayer(existingPlayer)); } foreach (IFieldObject <Item> existingItem in State.Items.Values) { sender.Send(FieldPacket.AddItem(existingItem, 123456)); } foreach (IFieldObject <Npc> existingNpc in State.Npcs.Values) { sender.Send(FieldPacket.AddNpc(existingNpc)); sender.Send(FieldObjectPacket.LoadNpc(existingNpc)); } foreach (IFieldObject <Portal> existingPortal in State.Portals.Values) { sender.Send(FieldPacket.AddPortal(existingPortal)); } foreach (IFieldObject <Mob> existingMob in State.Mobs.Values) { sender.Send(FieldPacket.AddMob(existingMob)); sender.Send(FieldObjectPacket.LoadMob(existingMob)); } if (State.InteractObjects.Values.Count > 0) { ICollection <IFieldObject <InteractObject> > balloons = State.InteractObjects.Values.Where(x => x.Value.Type == InteractObjectType.AdBalloon).ToList(); if (balloons.Count > 0) { foreach (IFieldObject <InteractObject> balloon in balloons) { sender.Send(InteractObjectPacket.AddAdBallons(balloon)); } } ICollection <IFieldObject <InteractObject> > objects = State.InteractObjects.Values.Where(x => x.Value.Type != InteractObjectType.AdBalloon).ToList(); if (objects.Count > 0) { sender.Send(InteractObjectPacket.AddInteractObjects(objects)); } } if (State.Cubes.IsEmpty && !player.Value.IsInDecorPlanner) { if (MapId == (int)Map.PrivateResidence) { Home home = GameServer.HomeManager.GetHome(player.Value.VisitingHomeId); if (home != null) { Dictionary <long, Cube> cubes = home.FurnishingInventory; foreach (Cube cube in cubes.Values.Where(x => x.PlotNumber == 1)) { IFieldObject <Cube> ugcCube = RequestFieldObject(cube); ugcCube.Coord = cube.CoordF; ugcCube.Rotation = cube.Rotation; State.AddCube(ugcCube); } } } else { List <Home> homes = GameServer.HomeManager.GetPlots(MapId); foreach (Home home in homes) { Dictionary <long, Cube> cubes = home.FurnishingInventory; foreach (Cube cube in cubes.Values.Where(x => x.PlotNumber != 1)) { IFieldObject <Cube> ugcCube = RequestFieldObject(cube); ugcCube.Coord = cube.CoordF; ugcCube.Rotation = cube.Rotation; State.AddCube(ugcCube); } } } } foreach (IFieldObject <GuideObject> guide in State.Guide.Values) { sender.Send(GuideObjectPacket.Add(guide)); } foreach (IFieldObject <HealingSpot> healingSpot in State.HealingSpots.Values) { sender.Send(RegionSkillPacket.Send(healingSpot.ObjectId, healingSpot.Value.Coord, new SkillCast(70000018, 1, 0, 1))); } foreach (IFieldObject <Instrument> instrument in State.Instruments.Values) { if (instrument.Value.Improvise) { sender.Send(InstrumentPacket.StartImprovise(instrument)); } else { sender.Send(InstrumentPacket.PlayScore(instrument)); } } List <BreakableObject> breakables = new List <BreakableObject>(); breakables.AddRange(State.BreakableActors.Values.ToList()); breakables.AddRange(State.BreakableNifs.Values.ToList()); sender.Send(BreakablePacket.LoadBreakables(breakables)); List <TriggerObject> triggerObjects = new List <TriggerObject>(); triggerObjects.AddRange(State.TriggerMeshes.Values.ToList()); triggerObjects.AddRange(State.TriggerEffects.Values.ToList()); triggerObjects.AddRange(State.TriggerCameras.Values.ToList()); triggerObjects.AddRange(State.TriggerActors.Values.ToList()); triggerObjects.AddRange(State.TriggerCubes.Values.ToList()); triggerObjects.AddRange(State.TriggerLadders.Values.ToList()); triggerObjects.AddRange(State.TriggerRopes.Values.ToList()); triggerObjects.AddRange(State.TriggerSounds.Values.ToList()); sender.Send(TriggerPacket.LoadTriggers(triggerObjects)); State.AddPlayer(player); if (MapLoopTask == null) { MapLoopTask = StartMapLoop(); //TODO: find a better place to initialise MapLoopTask } // Broadcast new player to all players in map Broadcast(session => { session.Send(FieldPacket.AddPlayer(player)); session.Send(FieldObjectPacket.LoadPlayer(player)); }); }
private static void HandleInteract(GameSession session, PacketReader packet) { Player player = session.Player; string id = packet.ReadString(); session.FieldManager.State.InteractObjects.TryGetValue(id, out IFieldObject <InteractObject> fieldInteractObject); if (fieldInteractObject is null) { return; } InteractObject interactObject = fieldInteractObject.Value; InteractObjectMetadata metadata = InteractObjectMetadataStorage.GetInteractObjectMetadata(interactObject.InteractId); QuestManager.OnInteractObject(player, interactObject.InteractId); switch (interactObject.Type) { case InteractObjectType.Binoculars: session.Send(InteractObjectPacket.Use(interactObject)); break; case InteractObjectType.Ui: session.Send(InteractObjectPacket.Use(interactObject)); break; case InteractObjectType.RankBoard: session.Send(WebOpenPacket.Open(metadata.Web.Url)); break; case InteractObjectType.AdBalloon: session.Send(PlayerHostPacket.AdBalloonWindow((AdBalloon)interactObject)); break; case InteractObjectType.Gathering: GatheringHelper.HandleGathering(session, metadata.Gathering.RecipeId, out int numDrop); session.Send(InteractObjectPacket.Use(interactObject, (short)(numDrop > 0 ? 0 : 1), numDrop)); break; case InteractObjectType.Common: // Unsure if all interact objects need to be set as disabled. interactObject.State = InteractObjectState.Disable; session.Send(InteractObjectPacket.Update(interactObject)); session.Send(InteractObjectPacket.Interact(interactObject)); foreach ((int questId, QuestState state) in metadata.Quests) { if (!player.QuestData.TryGetValue(questId, out QuestStatus questStatus) || questStatus.State != state) { continue; } interactObject.State = InteractObjectState.Activated; session.Send(InteractObjectPacket.Update(interactObject)); } DropItems(); TrophyManager.OnObjectInteract(player, interactObject.InteractId); if (interactObject is MapChest) { // Unsure if setting as activated is specific of map chests interactObject.State = InteractObjectState.Activated; // Delayed removal of the chest Task.Run(async() => { await Task.Delay(TimeSpan.FromSeconds(10)); session.FieldManager.State.RemoveInteractObject(interactObject.Id); session.FieldManager.BroadcastPacket(InteractObjectPacket.Update(interactObject)); session.FieldManager.BroadcastPacket(InteractObjectPacket.Remove(interactObject)); }); } return; } session.Send(InteractObjectPacket.Interact(interactObject)); void DropItems() { foreach (int boxId in metadata.Drop.IndividualDropBoxId) { ItemDropMetadata itemDropMetadataStorage = ItemDropMetadataStorage.GetItemDropMetadata(boxId); if (itemDropMetadataStorage is null) { continue; } foreach (DropGroup dropGroup in itemDropMetadataStorage.DropGroups) { foreach (DropGroupContent dropGroupContent in dropGroup.Contents) { foreach (int itemId in dropGroupContent.ItemIds) { int amount = Random.Shared.Next((int)dropGroupContent.MinAmount, (int)dropGroupContent.MaxAmount); Item item = new(itemId, amount, dropGroupContent.Rarity); session.FieldManager.AddItem(session.Player.FieldPlayer, item); } } } } foreach (int boxId in metadata.Drop.GlobalDropBoxId) { ItemDropMetadata itemDropMetadataStorage = ItemDropMetadataStorage.GetItemDropMetadata(boxId); if (itemDropMetadataStorage is null) { continue; } foreach (DropGroup dropGroup in itemDropMetadataStorage.DropGroups) { foreach (DropGroupContent dropGroupContent in dropGroup.Contents) { foreach (int itemId in dropGroupContent.ItemIds) { int amount = Random.Shared.Next((int)dropGroupContent.MinAmount, (int)dropGroupContent.MaxAmount); Item item = new(itemId, amount, dropGroupContent.Rarity); session.FieldManager.AddItem(session.Player.FieldPlayer, item); } } } } } }
public void AddPlayer(GameSession sender, IFieldObject <Player> player) { Debug.Assert(player.ObjectId > 0, "Player was added to field without initialized objectId."); player.Coord = player.Value.Coord; player.Value.MapId = MapId; // TODO: Determine new coordinates for player as well lock (Sessions) { Sessions.Add(sender); } // TODO: Send the initialization state of the field foreach (IFieldObject <Player> existingPlayer in State.Players.Values) { sender.Send(FieldPacket.AddPlayer(existingPlayer)); sender.Send(FieldObjectPacket.LoadPlayer(existingPlayer)); } foreach (IFieldObject <Item> existingItem in State.Items.Values) { sender.Send(FieldPacket.AddItem(existingItem, 123456)); } foreach (IFieldObject <Npc> existingNpc in State.Npcs.Values) { sender.Send(FieldPacket.AddNpc(existingNpc)); sender.Send(FieldObjectPacket.LoadNpc(existingNpc)); } foreach (IFieldObject <Portal> existingPortal in State.Portals.Values) { sender.Send(FieldPacket.AddPortal(existingPortal)); } foreach (IFieldObject <Mob> existingMob in State.Mobs.Values) { sender.Send(FieldPacket.AddMob(existingMob)); sender.Send(FieldObjectPacket.LoadMob(existingMob)); } if (State.InteractObjects.Values.Count > 0) { ICollection <IFieldObject <InteractObject> > balloons = State.InteractObjects.Values.Where(x => x.Value.Type == InteractObjectType.AdBalloon).ToList(); if (balloons.Count > 0) { foreach (IFieldObject <InteractObject> balloon in balloons) { sender.Send(InteractObjectPacket.AddAdBallons(balloon)); } } ICollection <IFieldObject <InteractObject> > objects = State.InteractObjects.Values.Where(x => x.Value.Type != InteractObjectType.AdBalloon).ToList(); if (objects.Count > 0) { sender.Send(InteractObjectPacket.AddInteractObjects(objects)); } } if (State.Cubes.Values.Count > 0) { sender.Send(CubePacket.LoadCubes(State.Cubes.Values)); } foreach (IFieldObject <GuideObject> guide in State.Guide.Values) { sender.Send(GuideObjectPacket.Add(guide)); } foreach (IFieldObject <HealingSpot> healingSpot in State.HealingSpots.Values) { sender.Send(RegionSkillPacket.Send(healingSpot.ObjectId, healingSpot.Value.Coord, new SkillCast(70000018, 1, 0, 1))); } foreach (IFieldObject <Instrument> instrument in State.Instruments.Values) { if (instrument.Value.Improvise) { sender.Send(InstrumentPacket.StartImprovise(instrument)); } else { sender.Send(InstrumentPacket.PlayScore(instrument)); } } State.AddPlayer(player); if (!State.HealingSpots.IsEmpty) { if (HealingSpotThread == null) { HealingSpotThread = StartHealingSpot(); } } // Broadcast new player to all players in map Broadcast(session => { session.Send(FieldPacket.AddPlayer(player)); session.Send(FieldObjectPacket.LoadPlayer(player)); }); }