private Task StartRegen(PlayerStatId statId, PlayerStatId regenStatId, PlayerStatId timeStatId) { return(Task.Run(async() => { await Task.Delay(Stats[timeStatId].Current); // TODO: Check if regen-enabled while (Stats[statId].Current < Stats[statId].Max) { lock (Stats) { Stats[statId] = AddStatRegen(statId, regenStatId); Session.Send(StatPacket.UpdateStats(Session.FieldPlayer, statId)); } await Task.Delay(Stats[timeStatId].Current); } })); }
public override void Handle(GameSession session, PacketReader packet) { packet.ReadInt(); // ? // Liftable: 00 00 00 00 00 // SendBreakable // Self Player player = session.Player; Account account = player.Account; session.EnterField(player); session.Send(StatPacket.SetStats(session.FieldPlayer)); session.Send(StatPointPacket.WriteTotalStatPoints(player)); if (account.IsVip()) { session.Send(BuffPacket.SendBuff(0, new Status(100000014, session.FieldPlayer.ObjectId, session.FieldPlayer.ObjectId, 1, (int)account.VIPExpiration, 1))); session.Send(PremiumClubPacket.ActivatePremium(session.FieldPlayer, account.VIPExpiration)); } session.Send(EmotePacket.LoadEmotes(player)); session.Send(ChatStickerPacket.LoadChatSticker(player)); session.Send(HomeCommandPacket.LoadHome(player)); session.Send(ResponseCubePacket.DecorationScore(account.Home)); session.Send(ResponseCubePacket.LoadHome(session.FieldPlayer.ObjectId, session.Player.Account.Home)); session.Send(ResponseCubePacket.ReturnMap(player.ReturnMapId)); IEnumerable <Cube> cubes = session.FieldManager.State.Cubes.Values.Where(x => x.Value.PlotNumber == 1 && (x.Value.Item.HousingCategory is ItemHousingCategory.Farming or ItemHousingCategory.Ranching)).Select(x => x.Value); foreach (Cube cube in cubes) { session.Send(FunctionCubePacket.UpdateFunctionCube(cube.CoordF.ToByte(), 2, 1)); } if (player.Party != null) { session.Send(PartyPacket.UpdatePlayer(player)); } session.Send(KeyTablePacket.SendHotbars(player.GameOptions)); List <GameEvent> gameEvents = DatabaseManager.Events.FindAll(); session.Send(GameEventPacket.Load(gameEvents)); }
private static void HandleAoeDamage(GameSession session, PacketReader packet) { List <IFieldObject <Mob> > mobs = new List <IFieldObject <Mob> >(); long skillSN = packet.ReadLong(); int unkValue = packet.ReadInt(); int playerObjectId = packet.ReadInt(); CoordF coords = packet.Read <CoordF>(); CoordF coords2 = packet.Read <CoordF>(); CoordF coords3 = packet.Read <CoordF>(); packet.ReadByte(); byte count = packet.ReadByte(); packet.ReadInt(); for (int i = 0; i < count; i++) { int entity = packet.ReadInt(); mobs.Add(session.FieldManager.State.Mobs.GetValueOrDefault(entity)); packet.ReadByte(); if (mobs[i] != null) { mobs[i].Value.UpdateStats(session.FieldPlayer.Value.SkillCast.GetDamage()); session.Send(StatPacket.UpdateMobStats(mobs[i])); // TODO: There needs to be a more centralized way to give rewards from killing mobs... // TODO: Add trophy, exp, meso and item drops if (mobs[i].Value.IsDead) { QuestHelper.UpdateQuest(session, mobs[i].Value.Id.ToString(), "npc"); } if (mobs[i].Value.Id == 29000128) // Temp fix for tutorial barrier { session.Send("4F 00 03 E8 03 00 00 00 00 00 00 00 00 00 00 00 00 80 3F".ToByteArray()); session.Send("4F 00 03 D0 07 00 00 00 00 00 00 00 00 00 00 00 00 80 3F".ToByteArray()); session.Send("4F 00 08 01 04 01 00 00".ToByteArray()); } } } session.Send(SkillDamagePacket.ApplyDamage(session.FieldPlayer, skillSN, unkValue, coords, mobs)); }
private static void IncreaseStats(GameSession session, Item item) { if (item.Stats.BasicStats.Count != 0) { foreach (NormalStat stat in item.Stats.BasicStats.Where(x => x.GetType() == typeof(NormalStat))) { session.Player.Stats.IncreaseMax((PlayerStatId)stat.Id, stat.Flat); } } if (item.Stats.BonusStats.Count != 0) { foreach (NormalStat stat in item.Stats.BonusStats.Where(x => x.GetType() == typeof(NormalStat))) { session.Player.Stats.IncreaseMax((PlayerStatId)stat.Id, stat.Flat); } } session.Send(StatPacket.SetStats(session.FieldPlayer)); }
private static void HandleCast(GameSession session, PacketReader packet) { long skillSN = packet.ReadLong(); int unkValue = packet.ReadInt(); int skillId = packet.ReadInt(); short skillLevel = packet.ReadShort(); packet.ReadByte(); CoordF coords = packet.Read <CoordF>(); packet.ReadShort(); SkillCast skillCast = session.Player.Cast(skillId, skillLevel, skillSN, unkValue); if (skillCast != null) { session.Send(SkillUsePacket.SkillUse(skillCast, coords)); session.Send(StatPacket.SetStats(session.FieldPlayer)); } }
private static void IncreaseStats(GameSession session, Item item) { if (item.Stats.BasicStats.Count != 0) { foreach (NormalStat stat in item.Stats.BasicStats.OfType <NormalStat>()) { session.Player.Stats[stat.ItemAttribute].IncreaseBonus(stat.Flat); } } if (item.Stats.BonusStats.Count != 0) { foreach (NormalStat stat in item.Stats.BonusStats.OfType <NormalStat>()) { session.Player.Stats[stat.ItemAttribute].IncreaseBonus(stat.Flat); } } session.Send(StatPacket.SetStats(session.Player.FieldPlayer)); }
public bool LevelUp() { if (!ExpMetadataStorage.LevelExist((short)(Level + 1))) { return(false); } Level++; TrophyManager.OnLevelUp(Player); Player.Stats.AddBaseStats(Player); Player.FieldPlayer.RecoverHp(FieldPlayer.Stats[StatId.Hp].Bonus); Session.FieldManager.BroadcastPacket(ExperiencePacket.LevelUp(FieldPlayer.ObjectId, Level)); Session.Send(StatPacket.SetStats(FieldPlayer)); QuestHelper.GetNewQuests(Player); return(true); }
private void HandleEquipItem(GameSession session, PacketReader packet) { long itemUid = packet.ReadLong(); string equipSlotStr = packet.ReadUnicodeString(); if (!Enum.TryParse(equipSlotStr, out ItemSlot equipSlot)) { logger.Warning("Unknown equip slot: " + equipSlotStr); return; } // Remove the item from the users inventory InventoryController.Remove(session, itemUid, out Item item); // TODO: Move unequipped item into the correct slot // Move previously equipped item back to inventory if (session.Player.Equips.Remove(equipSlot, out Item prevItem)) { InventoryController.Add(session, prevItem, false); session.FieldManager.BroadcastPacket(EquipmentPacket.UnequipItem(session.FieldPlayer, prevItem)); } // Equip new item session.Player.Equips[equipSlot] = item; session.FieldManager.BroadcastPacket(EquipmentPacket.EquipItem(session.FieldPlayer, item, equipSlot)); // TODO - Increase stats based on the item stats itself session.Player.Stats.CritRate.Max += 12; session.Player.Stats.CritRate.Total += 12; session.Player.Stats.MinAtk.Max += 15; session.Player.Stats.MinAtk.Total += 15; session.Player.Stats.MaxAtk.Max += 17; session.Player.Stats.MaxAtk.Total += 17; session.Player.Stats.MagAtk.Max += 15; session.Player.Stats.MagAtk.Total += 15; session.Send(StatPacket.SetStats(session.FieldPlayer)); }
public override void Handle(GameSession session, PacketReader packet) { packet.ReadInt(); // ? // Liftable: 00 00 00 00 00 // SendBreakable // Self session.EnterField(session.Player.MapId); session.Send(StatPacket.SetStats(session.FieldPlayer)); session.Send(StatPointPacket.WriteTotalStatPoints(session.Player)); foreach (MasteryExp mastery in session.Player.Levels.MasteryExp) { session.Send(MasteryPacket.SetExp(mastery.Type, mastery.CurrentExp)); } if (session.Player.IsVip()) { session.Send(PremiumClubPacket.ActivatePremium(session.FieldPlayer, session.Player.VIPExpiration)); } session.Send(EmotePacket.LoadEmotes(session.Player)); session.Send(ChatStickerPacket.LoadChatSticker(session.Player)); session.Send(ResponseCubePacket.LoadHome(session.FieldPlayer)); // Normally skill layout would be loaded from a database QuickSlot arrowStream = QuickSlot.From(10500001); QuickSlot arrowBarrage = QuickSlot.From(10500011); QuickSlot eagleGlide = QuickSlot.From(10500151); QuickSlot testSkill = QuickSlot.From(10500153); if (session.Player.GameOptions.TryGetHotbar(0, out Hotbar mainHotbar)) { /* * mainHotbar.MoveQuickSlot(4, arrowStream); * mainHotbar.MoveQuickSlot(5, arrowBarrage); * mainHotbar.MoveQuickSlot(6, eagleGlide); * mainHotbar.MoveQuickSlot(7, testSkill); */ session.Send(KeyTablePacket.SendHotbars(session.Player.GameOptions)); } session.Send(GameEventPacket.Load()); }
private void HealingSpot() { foreach (IFieldObject <HealingSpot> healingSpot in State.HealingSpots.Values) { CoordS healingCoord = healingSpot.Value.Coord; foreach (IFieldObject <Player> player in State.Players.Values) { if ((healingCoord - player.Coord.ToShort()).Length() < Block.BLOCK_SIZE * 2 && healingCoord.Z == player.Coord.ToShort().Z - 1) // 3x3x1 area { int healAmount = (int)(player.Value.Stats[PlayerStatId.Hp].Max * 0.03); Status status = new Status(new SkillCast(70000018, 1, 0, 1), target: player.ObjectId, source: healingSpot.ObjectId, stacks: 1); player.Value.Session.Send(BuffPacket.SendBuff(0, status)); BroadcastPacket(SkillDamagePacket.Heal(status, healAmount)); player.Value.Session.Player.Stats.Increase(PlayerStatId.Hp, healAmount); player.Value.Session.Send(StatPacket.UpdateStats(player, PlayerStatId.Hp)); } } } }
public override void Execute(GameCommandTrigger trigger) { short level = trigger.Get <short>("level"); if (level <= 0) { trigger.Session.SendNotice("Level must be a number or more than 0."); return; } Player player = trigger.Session.Player; // Reset stats to default player.Stats = new(player.Job); player.Stats.AddBaseStats(player, level); trigger.Session.Send(StatPacket.SetStats(player.FieldPlayer)); trigger.Session.FieldManager.BroadcastPacket(StatPacket.SetStats(player.FieldPlayer), trigger.Session); player.Levels.SetLevel(level); }
private Task StartRegen(PlayerStatId statId, PlayerStatId regenStatId, PlayerStatId timeStatId) { // TODO: merge regen updates with larger packets return(Task.Run(async() => { while (true) { await Task.Delay(Stats[timeStatId].Current); lock (Stats) { if (Stats[statId].Current >= Stats[statId].Max) { return; } // TODO: Check if regen-enabled Stats[statId] = AddStatRegen(statId, regenStatId); Session.Send(StatPacket.UpdateStats(Session.FieldPlayer, statId)); } } })); }
private Task StartHealingSpot(GameSession session, IFieldObject <Player> player) { int healAmount = 30; Status status = new Status(new SkillCast(70000018, 1, 0, 1), player.ObjectId, player.ObjectId, 1, healAmount); return(Task.Run(async() => { while (!State.Players.IsEmpty) { CoordS healingCoord = MapEntityStorage.GetHealingSpot(MapId); if ((healingCoord - player.Coord.ToShort()).Length() < Block.BLOCK_SIZE * 2 && healingCoord.Z == player.Coord.ToShort().Z - 1) // 3x3x1 area { session.Send(BuffPacket.SendBuff(0, status)); session.Send(SkillDamagePacket.ApplyHeal(player, status)); session.Player.Stats.Increase(PlayerStatId.Hp, healAmount); session.Send(StatPacket.UpdateStats(player, PlayerStatId.Hp)); } await Task.Delay(1000); } })); }
private void HandleAoeDamage(GameSession session, PacketReader packet) { List <IFieldObject <Mob> > mobs = new List <IFieldObject <Mob> >(); long skillUid = packet.ReadLong(); int someValue = packet.ReadInt(); int playerObjectId = packet.ReadInt(); CoordF coords = packet.Read <CoordF>(); CoordF coords2 = packet.Read <CoordF>(); CoordF coords3 = packet.Read <CoordF>(); packet.ReadByte(); byte count = packet.ReadByte(); packet.ReadInt(); for (int i = 0; i < count; i++) { mobs.Add(session.FieldManager.State.Mobs.GetValueOrDefault(packet.ReadInt())); packet.ReadByte(); session.Send(StatPacket.UpdateMobStats(mobs[i])); } session.Send(SkillDamagePacket.ApplyDamage(session.FieldPlayer, skillUid, someValue, coords, mobs)); }
private static void HandleFirstSent(GameSession session, PacketReader packet) { long skillSN = packet.ReadLong(); int unkValue = packet.ReadInt(); int skillId = packet.ReadInt(); short skillLevel = packet.ReadShort(); packet.ReadByte(); CoordF coords = packet.Read <CoordF>(); packet.ReadShort(); SkillCast skillCast = new SkillCast(skillId, skillLevel, skillSN, unkValue); int skillCost = skillCast.GetCost(); if (session.Player.Stats[PlayerStatId.Spirit].Current >= skillCost) { session.FieldPlayer.Value.SkillCast = skillCast; session.Player.ConsumeSp(skillCost); session.Send(SkillUsePacket.SkillUse(skillCast, coords)); session.Send(StatPacket.SetStats(session.FieldPlayer)); } }
public override void Handle(GameSession session, PacketReader packet) { packet.ReadInt(); // ? // Liftable: 00 00 00 00 00 // SendBreakable // Self Player player = session.Player; Account account = player.Account; session.EnterField(player); session.Send(StatPacket.SetStats(session.FieldPlayer)); session.Send(StatPointPacket.WriteTotalStatPoints(player)); if (account.IsVip()) { session.Send(BuffPacket.SendBuff(0, new Status(100000014, session.FieldPlayer.ObjectId, session.FieldPlayer.ObjectId, 1, (int)account.VIPExpiration, 1))); session.Send(PremiumClubPacket.ActivatePremium(session.FieldPlayer, account.VIPExpiration)); } session.Send(EmotePacket.LoadEmotes(player)); session.Send(ChatStickerPacket.LoadChatSticker(player)); session.Send(HomeCommandPacket.LoadHome(player)); session.Send(ResponseCubePacket.DecorationScore(account.Home)); session.Send(ResponseCubePacket.LoadHome(session.FieldPlayer)); session.Send(ResponseCubePacket.ReturnMap(player.ReturnMapId)); if (player.Party != null) { session.Send(PartyPacket.UpdatePlayer(player)); } session.Send(KeyTablePacket.SendHotbars(player.GameOptions)); List <GameEvent> gameEvents = DatabaseManager.Events.FindAll(); session.Send(GameEventPacket.Load(gameEvents)); }
private void HandleEquipItem(GameSession session, PacketReader packet) { long itemUid = packet.ReadLong(); string equipSlotStr = packet.ReadUnicodeString(); if (!Enum.TryParse(equipSlotStr, out ItemSlot equipSlot)) { logger.Warning("Unknown equip slot: " + equipSlotStr); return; } // Remove the item from the users inventory InventoryController.Remove(session, itemUid, out Item item); // Equip cosmetic if (item.InventoryTab == InventoryTab.Outfit) { // Move previously equipped item back to inventory if (session.Player.Cosmetics.Remove(equipSlot, out Item prevItem)) { prevItem.Slot = item.Slot; InventoryController.Add(session, prevItem, false); session.FieldManager.BroadcastPacket(EquipmentPacket.UnequipItem(session.FieldPlayer, prevItem)); } // Handle unequipping off-hand when equipping two-handed weapons if (item.IsTwoHand) { if (session.Player.Cosmetics.Remove(ItemSlot.LH, out Item prevItem2)) { prevItem2.Slot = -1; if (prevItem == null) { prevItem2.Slot = item.Slot; } InventoryController.Add(session, prevItem2, false); session.FieldManager.BroadcastPacket(EquipmentPacket.UnequipItem(session.FieldPlayer, prevItem2)); } } // Handle unequipping two-handed main-hands when equipping off-hand weapons if (item.ItemSlot == ItemSlot.LH && session.Player.Cosmetics[ItemSlot.RH] != null && session.Player.Cosmetics[ItemSlot.RH].IsTwoHand) { if (session.Player.Cosmetics.Remove(ItemSlot.RH, out Item prevItem2)) { prevItem2.Slot = item.Slot; InventoryController.Add(session, prevItem2, false); session.FieldManager.BroadcastPacket(EquipmentPacket.UnequipItem(session.FieldPlayer, prevItem2)); } } // Equip new item session.Player.Cosmetics[equipSlot] = item; session.FieldManager.BroadcastPacket(EquipmentPacket.EquipItem(session.FieldPlayer, item, equipSlot)); } // Equip gear else { // Move previously equipped item back to inventory if (session.Player.Equips.Remove(equipSlot, out Item prevItem)) { prevItem.Slot = item.Slot; InventoryController.Add(session, prevItem, false); session.FieldManager.BroadcastPacket(EquipmentPacket.UnequipItem(session.FieldPlayer, prevItem)); } // Handle unequipping off-hand when equipping two-handed weapons if (item.IsTwoHand) { if (session.Player.Equips.Remove(ItemSlot.LH, out Item prevItem2)) { prevItem2.Slot = -1; if (prevItem == null) { prevItem2.Slot = item.Slot; } InventoryController.Add(session, prevItem2, false); session.FieldManager.BroadcastPacket(EquipmentPacket.UnequipItem(session.FieldPlayer, prevItem2)); } } // Handle unequipping two-handed main-hands when equipping off-hand weapons if (item.ItemSlot == ItemSlot.LH && session.Player.Equips[ItemSlot.RH] != null && session.Player.Equips[ItemSlot.RH].IsTwoHand) { if (session.Player.Equips.Remove(ItemSlot.RH, out Item prevItem2)) { prevItem2.Slot = item.Slot; InventoryController.Add(session, prevItem2, false); session.FieldManager.BroadcastPacket(EquipmentPacket.UnequipItem(session.FieldPlayer, prevItem2)); } } // Equip new item session.Player.Equips[equipSlot] = item; session.FieldManager.BroadcastPacket(EquipmentPacket.EquipItem(session.FieldPlayer, item, equipSlot)); // TODO - Increase stats based on the item stats itself session.Player.Stats.CritRate.Max += 12; session.Player.Stats.CritRate.Total += 12; session.Player.Stats.MinAtk.Max += 15; session.Player.Stats.MinAtk.Total += 15; session.Player.Stats.MaxAtk.Max += 17; session.Player.Stats.MaxAtk.Total += 17; session.Player.Stats.MagAtk.Max += 15; session.Player.Stats.MagAtk.Total += 15; session.Send(StatPacket.SetStats(session.FieldPlayer)); } }
public override void Handle(GameSession session, PacketReader packet) { packet.ReadInt(); // ? // Liftable: 00 00 00 00 00 // SendBreakable // Self session.EnterField(session.Player.MapId); session.Send(StatPacket.SetStats(session.FieldPlayer)); session.Send(StatPointPacket.WriteTotalStatPoints(session.Player)); session.Send(EmotePacket.LoadEmotes(session.Player)); session.Send(ChatStickerPacket.LoadChatSticker(session.Player)); // Normally skill layout would be loaded from a database QuickSlot arrowStream = QuickSlot.From(10500001); QuickSlot arrowBarrage = QuickSlot.From(10500011); QuickSlot eagleGlide = QuickSlot.From(10500151); QuickSlot testSkill = QuickSlot.From(10500153); if (session.Player.GameOptions.TryGetHotbar(0, out Hotbar mainHotbar)) { /* * mainHotbar.MoveQuickSlot(4, arrowStream); * mainHotbar.MoveQuickSlot(5, arrowBarrage); * mainHotbar.MoveQuickSlot(6, eagleGlide); * mainHotbar.MoveQuickSlot(7, testSkill); */ session.Send(KeyTablePacket.SendHotbars(session.Player.GameOptions)); } // Add catalysts for testing Item item = new Item(40100001) { Amount = 99999 }; Item item2 = new Item(40100001) { Amount = 90000 }; Item item3 = new Item(20302228) { Amount = 1 }; InventoryController.Add(session, item, true); InventoryController.Add(session, item2, true); InventoryController.Add(session, item3, true); //Add mail for testing //System mail without any item Mail sysMail = new Mail ( 101, session.Player.CharacterId, "50000002", "", "", 0, DateTimeOffset.UtcNow.ToUnixTimeSeconds(), null ); // System mail with an item List <Item> items = new List <Item> { new Item(40100001) // 20302228 { CreationTime = DateTimeOffset.UtcNow.ToUnixTimeSeconds(), Owner = session.Player, Amount = 10000 } }; Mail sysItemMail = new Mail ( 101, session.Player.CharacterId, "53000042", "", "", 0, DateTimeOffset.UtcNow.ToUnixTimeSeconds(), items ); // Regular mail Mail regMail = new Mail ( 1, session.Player.CharacterId, session.Player.Name, "Test Title", "Test Body", 0, DateTimeOffset.UtcNow.ToUnixTimeSeconds(), null ); session.Player.Mailbox.AddOrUpdate(sysItemMail); session.Player.Mailbox.AddOrUpdate(sysMail); session.Player.Mailbox.AddOrUpdate(regMail); }
private static void HandleDamage(GameSession session, PacketReader packet) { List <(IFieldObject <Mob>, DamageHandler)> mobs = new List <(IFieldObject <Mob>, DamageHandler)>(); long skillSN = packet.ReadLong(); int attackCounter = packet.ReadInt(); int playerObjectId = packet.ReadInt(); CoordF position = packet.Read <CoordF>(); CoordF impactPos = packet.Read <CoordF>(); CoordF rotation = packet.Read <CoordF>(); int attackPoint = packet.ReadByte(); byte count = packet.ReadByte(); packet.ReadInt(); bool isCrit = DamageHandler.RollCrit(session.Player.Stats[PlayerStatId.CritRate].Current); for (int i = 0; i < count; i++) { int entity = packet.ReadInt(); packet.ReadByte(); IFieldObject <Mob> mob = session.FieldManager.State.Mobs.GetValueOrDefault(entity); if (mob == null) { continue; } DamageHandler damage = DamageHandler.CalculateDamage(session.FieldPlayer.Value.SkillCast, session.FieldPlayer.Value, mob.Value, isCrit); mob.Value.Damage(damage.Damage); session.Send(StatPacket.UpdateMobStats(mob)); if (mob.Value.IsDead) { HandleMobKill(session, mob); } mobs.Add((mob, damage)); // TODO: Check if the skill is a debuff for an entity SkillCast skillCast = session.FieldPlayer.Value.SkillCast; if (skillCast.IsDebuffElement() || skillCast.IsDebuffToEntity() || skillCast.IsDebuffElement()) { Status status = new Status(session.FieldPlayer.Value.SkillCast, mob.ObjectId, session.FieldPlayer.ObjectId, 1); StatusHandler.Handle(session, status); } } // TODO: Verify if its the player or an ally if (session.FieldPlayer.Value.SkillCast.IsHeal()) { Status status = new Status(session.FieldPlayer.Value.SkillCast, session.FieldPlayer.ObjectId, session.FieldPlayer.ObjectId, 1); StatusHandler.Handle(session, status); // TODO: Heal based on stats session.FieldManager.BroadcastPacket(SkillDamagePacket.Heal(status, 50)); session.FieldPlayer.Value.Stats.Increase(PlayerStatId.Hp, 50); session.Send(StatPacket.UpdateStats(session.FieldPlayer, PlayerStatId.Hp)); } else { session.FieldManager.BroadcastPacket(SkillDamagePacket.Damage(skillSN, attackCounter, position, rotation, session.FieldPlayer, mobs)); } }
private static void HandleDamage(GameSession session, PacketReader packet) { long skillSN = packet.ReadLong(); int attackCounter = packet.ReadInt(); int playerObjectId = packet.ReadInt(); CoordF position = packet.Read <CoordF>(); CoordF impactPos = packet.Read <CoordF>(); CoordF rotation = packet.Read <CoordF>(); int attackPoint = packet.ReadByte(); byte count = packet.ReadByte(); packet.ReadInt(); IFieldActor <Player> fieldPlayer = session.Player.FieldPlayer; bool isCrit = DamageHandler.RollCrit(session.Player.Stats[StatId.CritRate].Total); // TODO: Check if skillSN matches server's current skill for the player // TODO: Verify if its the player or an ally if (fieldPlayer.SkillCast.IsHeal()) { Status status = new(fieldPlayer.SkillCast, fieldPlayer.ObjectId, fieldPlayer.ObjectId, 1); StatusHandler.Handle(session, status); // TODO: Heal based on stats session.FieldManager.BroadcastPacket(SkillDamagePacket.Heal(status, 50)); fieldPlayer.Stats[StatId.Hp].Increase(50); session.Send(StatPacket.UpdateStats(fieldPlayer, StatId.Hp)); } else { List <DamageHandler> damages = new(); for (int i = 0; i < count; i++) { int entityId = packet.ReadInt(); packet.ReadByte(); IFieldActor <NpcMetadata> mob = session.FieldManager.State.Mobs.GetValueOrDefault(entityId); if (mob == null) { continue; } DamageHandler damage = DamageHandler.CalculateDamage(fieldPlayer.SkillCast, fieldPlayer, mob, isCrit); mob.Damage(damage); // TODO: Move logic to Damage() session.FieldManager.BroadcastPacket(StatPacket.UpdateMobStats(mob)); if (mob.IsDead) { HandleMobKill(session, mob); } damages.Add(damage); // TODO: Check if the skill is a debuff for an entity SkillCast skillCast = fieldPlayer.SkillCast; if (skillCast.IsDebuffElement() || skillCast.IsDebuffToEntity() || skillCast.IsDebuffElement()) { Status status = new(fieldPlayer.SkillCast, mob.ObjectId, fieldPlayer.ObjectId, 1); StatusHandler.Handle(session, status); } } session.FieldManager.BroadcastPacket(SkillDamagePacket.Damage(skillSN, attackCounter, position, rotation, fieldPlayer, damages)); } }
public virtual void Heal(GameSession session, Status status, int amount) { session.FieldManager.BroadcastPacket(SkillDamagePacket.Heal(status, amount)); Stats[StatAttribute.Hp].AddValue(amount); session.Send(StatPacket.UpdateStats(this, StatAttribute.Hp)); }
private static void HandleResetStatDistribution(GameSession session) { session.Player.Stats.ResetAllocations(session.Player.StatPointDistribution); session.Send(StatPointPacket.WriteStatPointDistribution(session.Player)); // Deprecate? session.Send(StatPacket.SetStats(session.FieldPlayer)); }
public override void Handle(GameSession session, PacketReader packet) { packet.ReadInt(); // ? // Liftable: 00 00 00 00 00 // SendBreakable // Self Player player = session.Player; Account account = player.Account; session.EnterField(player); session.Send(StatPacket.SetStats(player.FieldPlayer)); session.Send(StatPointPacket.WriteTotalStatPoints(player)); session.Send(StatPointPacket.WriteTotalStatPoints(player)); // This packet is sent twice on GMS, not sure why session.Send(StatPointPacket.WriteStatPointDistribution(player)); session.Send(SkillPointPacket.ExtraSkillPoints(player)); if (player.ActivePet is not null) { player.ActivePet.SetMetadataValues(); Pet pet = session.FieldManager.RequestPet(player.ActivePet, player.FieldPlayer); if (pet is not null) { player.FieldPlayer.ActivePet = pet; session.Send(ResponsePetPacket.LoadPetSettings(pet)); session.Send(NoticePacket.Notice(SystemNotice.PetSummonOn, NoticeType.Chat | NoticeType.FastText)); } } if (account.IsVip()) { session.Send(BuffPacket.SendBuff(0, new(100000014, player.FieldPlayer.ObjectId, player.FieldPlayer.ObjectId, 1, (int)account.VIPExpiration, 1))); session.Send(PremiumClubPacket.ActivatePremium(player.FieldPlayer, account.VIPExpiration)); } session.Send(EmotePacket.LoadEmotes(player)); session.Send(MacroPacket.LoadControls(player.Macros)); session.Send(ChatStickerPacket.LoadChatSticker(player)); session.Send(ResponseCubePacket.DecorationScore(account.Home)); session.Send(ResponseCubePacket.LoadHome(player.FieldPlayer.ObjectId, player.Account.Home)); session.Send(ResponseCubePacket.ReturnMap(player.ReturnMapId)); session.Send(LapenshardPacket.Load(player.Inventory.LapenshardStorage)); IEnumerable <Cube> cubes = session.FieldManager.State.Cubes.Values .Where(x => x.Value.PlotNumber == 1 && x.Value.Item.HousingCategory is ItemHousingCategory.Farming or ItemHousingCategory.Ranching) .Select(x => x.Value); foreach (Cube cube in cubes) { session.Send(FunctionCubePacket.UpdateFunctionCube(cube.CoordF.ToByte(), 2, 1)); } if (player.Party is not null) { session.Send(PartyPacket.UpdatePlayer(player)); } GlobalEvent globalEvent = GameServer.GlobalEventManager.GetCurrentEvent(); if (globalEvent is not null && !MapMetadataStorage.MapIsInstancedOnly(player.MapId)) { session.Send(GlobalPortalPacket.Notice(globalEvent)); } FieldWar fieldWar = GameServer.FieldWarManager.CurrentFieldWar; if (fieldWar is not null && !MapMetadataStorage.MapIsInstancedOnly(player.MapId) && fieldWar.MapId != player.MapId) { session.Send(FieldWarPacket.LegionPopup(fieldWar.Id, fieldWar.EntryClosureTime.ToUnixTimeSeconds())); } session.Send(KeyTablePacket.SendHotbars(player.GameOptions)); TrophyManager.OnMapEntered(player, player.MapId); QuestManager.OnMapEnter(player, player.MapId); player.InitializeEffects(); }
public override void Handle(GameSession session, PacketReader packet) { long accountId = packet.ReadLong(); AuthData authData = DatabaseManager.AuthData.GetByAccountId(accountId); Player dbPlayer = DatabaseManager.Characters.FindPlayerById(authData.OnlineCharacterId); // Backwards seeking because we read accountId here packet.Skip(-8); HandleCommon(session, packet); session.InitPlayer(dbPlayer); Player player = session.Player; player.Session = session; player.Wallet.Meso.Session = session; player.Wallet.ValorToken.Session = session; player.Wallet.Treva.Session = session; player.Wallet.Rue.Session = session; player.Wallet.HaviFruit.Session = session; player.Account.Meret.Session = session; player.Account.GameMeret.Session = session; player.Account.EventMeret.Session = session; player.Account.MesoToken.Session = session; player.Account.BankInventory.Mesos.Session = session; player.Levels.Player = player; player.BuddyList = GameServer.BuddyManager.GetBuddies(player.CharacterId); player.Mailbox = GameServer.MailManager.GetMails(player.CharacterId); GameServer.PlayerManager.AddPlayer(player); GameServer.BuddyManager.SetFriendSessions(player); // Only send buddy login notification if player is not changing channels if (!player.IsMigrating) { player.UpdateBuddies(); } if (player.GuildId != 0) { Guild guild = GameServer.GuildManager.GetGuildById(player.GuildId); player.Guild = guild; GuildMember guildMember = guild.Members.First(x => x.Id == player.CharacterId); guildMember.Player.Session = session; player.GuildMember = guildMember; session.Send(GuildPacket.UpdateGuild(guild)); guild.BroadcastPacketGuild(GuildPacket.MemberJoin(player)); guild.BroadcastPacketGuild(GuildPacket.MemberLoggedIn(player), session); } player.IsMigrating = false; //session.Send(0x27, 0x01); // Meret market related...? session.Send(MushkingRoyaleSystemPacket.LoadStats(session.Player.Account.MushkingRoyaleStats)); session.Send(MushkingRoyaleSystemPacket.LoadMedals(session.Player.Account)); player.GetUnreadMailCount(); session.Send(BuddyPacket.Initialize()); session.Send(BuddyPacket.LoadList(player.BuddyList)); session.Send(BuddyPacket.EndList(player.BuddyList.Count)); // Meret market //session.Send("6E 00 0B 00 00 00 00 00 00 00 00 00 00 00 00".ToByteArray()); //session.Send("6E 00 0C 00 00 00 00".ToByteArray()); // UserConditionEvent //session.Send("BF 00 00 00 00 00 00".ToByteArray()); // PCBangBonus //session.Send("A7 00 03 00 00 00 00 00 00 00 00 00 00 00 00 00".ToByteArray()); TimeSyncPacket.SetInitial1(); TimeSyncPacket.SetInitial2(); TimeSyncPacket.Request(); session.Send(StatPacket.SetStats(session.Player.FieldPlayer)); session.Player.ClientTickSyncLoop(); session.Send(DynamicChannelPacket.DynamicChannel()); session.Send(ServerEnterPacket.Enter(session)); // SendUgc f(0x16), SendCash f(0x09), SendContentShutdown f(0x01, 0x04), SendPvp f(0x0C) session.Send(SyncNumberPacket.Send()); // 0x112, Prestige f(0x00, 0x07) session.Send(PrestigePacket.Prestige(player)); // Load inventory tabs foreach (InventoryTab tab in Enum.GetValues(typeof(InventoryTab))) { player.Inventory.LoadInventoryTab(session, tab); } if (player.Account.HomeId != 0) { Home home = GameServer.HomeManager.GetHomeById(player.Account.HomeId); player.Account.Home = home; session.Send(WarehouseInventoryPacket.StartList()); int counter = 0; foreach (KeyValuePair <long, Item> kvp in home.WarehouseInventory) { session.Send(WarehouseInventoryPacket.Load(kvp.Value, ++counter)); } session.Send(WarehouseInventoryPacket.EndList()); session.Send(FurnishingInventoryPacket.StartList()); foreach (Cube cube in home.FurnishingInventory.Values.Where(x => x.Item != null)) { session.Send(FurnishingInventoryPacket.Load(cube)); } session.Send(FurnishingInventoryPacket.EndList()); } session.Send(QuestPacket.StartList()); session.Send(QuestPacket.Packet1F()); session.Send(QuestPacket.Packet20()); IEnumerable <List <QuestStatus> > packetCount = player.QuestData.Values.ToList().SplitList(200); // Split the quest list in 200 quests per packet foreach (List <QuestStatus> item in packetCount) { session.Send(QuestPacket.SendQuests(item)); } session.Send(QuestPacket.EndList()); session.Send(TrophyPacket.WriteTableStart()); List <Trophy> trophyList = new(player.TrophyData.Values); IEnumerable <List <Trophy> > trophyListPackets = trophyList.SplitList(60); foreach (List <Trophy> trophy in trophyListPackets) { session.Send(TrophyPacket.WriteTableContent(trophy)); } // SendQuest, SendAchieve, SendManufacturer, SendUserMaid session.Send(UserEnvPacket.SetTitles(player)); session.Send(UserEnvPacket.Send04()); session.Send(UserEnvPacket.Send05()); session.Send(UserEnvPacket.UpdateLifeSkills(player.GatheringCount)); session.Send(UserEnvPacket.Send09()); session.Send(UserEnvPacket.Send10()); session.Send(UserEnvPacket.Send12()); // SendMeretMarket f(0xC9) session.Send(FishingPacket.LoadAlbum(player)); // SendPvp f(0x16,0x17), ResponsePet f(0x07), 0xF6 // CharacterAbility // E1 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 // Key bindings and skill slots would normally be loaded from a database // If the character is not a new character, this is what we would send session.Send(KeyTablePacket.SendFullOptions(player.GameOptions)); if (player.MapId == (int)Map.UnknownLocation) // tutorial map { session.Send(KeyTablePacket.AskKeyboardOrMouse()); } // SendKeyTable f(0x00), SendGuideRecord f(0x03), GameEvent f(0x00) // SendBannerList f(0x19), SendRoomDungeon f(0x05, 0x14, 0x17) // FieldEntrance session.Send("19 00 00 65 00 00 00 29 7C 7D 01 0C 4D A1 6F 01 0C D3 1A 5F 01 0C EF 03 00 00 01 A2 3C 31 01 0C 3F 0C B7 0D 01 6B 55 5F 01 0C 3A 77 31 01 0C B1 98 BA 01 0C 03 90 5F 01 0C F9 7A 40 01 0C 91 B5 40 01 0C F9 57 31 01 0C 2F C7 BB 0D 01 81 97 7D 01 0C C2 70 5F 01 0C 51 96 40 01 0C B9 38 31 01 0C 41 78 7D 01 0C 65 9D 6F 01 0C 83 51 5F 01 0C 52 73 31 01 0C FF E0 B8 0D 01 11 77 40 01 0C A9 B1 40 01 0C 11 54 31 01 0C DA 6C 5F 01 0C 69 92 40 01 0C D1 34 31 01 0C 7D 99 6F 01 0C 03 13 5F 01 0C 69 6F 31 01 0C 32 88 5F 01 0C 9B 4D 5F 01 0C FF 6F B6 0D 01 29 73 40 01 0C C1 AD 40 01 0C 29 50 31 01 0C 81 8E 40 01 0C E9 30 31 01 0C 09 CE 8C 01 0C 95 95 6F 01 0C 1B 0F 5F 01 0C 4A 84 5F 01 0C B3 49 5F 01 0C 82 6B 31 01 0C 4F 15 BC 0D 01 F9 8C BA 01 00 D9 A9 40 01 0C 41 4C 31 01 0C EF B9 B8 0D 01 99 8A 40 01 0C 21 CA 8C 01 0C 01 AD 6F 01 0C 33 0B 5F 01 0C 99 67 31 01 0C 62 80 5F 01 0C CB 45 5F 01 0C 79 08 9C 01 0C F1 A5 40 01 0C E1 87 7D 01 0C BB 9B 5F 01 0C B1 86 40 01 0C 39 C6 8C 01 0C 7A 7C 5F 01 0C B2 63 31 01 0C 29 85 BA 01 0E 91 04 9C 01 0C 09 A2 40 01 0C 71 44 31 01 0C F9 83 7D 01 0C 1D A9 6F 01 0C D3 97 5F 01 0C C9 82 40 01 0C 51 C2 8C 01 0C 61 BD 40 01 0C C9 5F 31 01 0C 51 9F 7D 01 0C 92 78 5F 01 0C 0F 08 B9 0D 01 A9 00 9C 01 0C 89 40 31 01 0C 11 80 7D 01 0C 35 A5 6F 01 0C BB 1E 5F 01 0C 53 59 5F 01 0C E9 03 00 00 01 22 7B 31 01 0C EB 93 5F 01 0C EA 03 00 00 01 E1 7E 40 01 0C 69 BE 8C 01 0C 79 B9 40 01 0C E1 5B 31 01 0C EB 03 00 00 01 69 9B 7D 01 0C AA 74 5F 01 0C EC 03 00 00 01 ED 03 00 00 01 C1 FC 9B 01 0C EE 03 00 00 01".ToByteArray()); // 0xF0, ResponsePet P(0F 01) // RequestFieldEnter //session.Send("16 00 00 41 75 19 03 00 01 8A 42 0F 00 00 00 00 00 00 C0 28 C4 00 40 03 44 00 00 16 44 00 00 00 00 00 00 00 00 55 FF 33 42 E8 49 01 00".ToByteArray()); session.Send(RequestFieldEnterPacket.RequestEnter(session.Player.FieldPlayer)); Party party = GameServer.PartyManager.GetPartyByMember(player.CharacterId); if (party != null) { player.Party = party; party.BroadcastPacketParty(PartyPacket.LoginNotice(player), session); session.Send(PartyPacket.Create(party, false)); } // SendUgc: 15 01 00 00 00 00 00 00 00 00 00 00 00 4B 00 00 00 // SendHomeCommand: 00 E1 0F 26 89 7F 98 3C 26 00 00 00 00 00 00 00 00 session.Player.TimeSyncLoop(); session.Send(TimeSyncPacket.SetSessionServerTick(0)); //session.Send("B9 00 00 E1 0F 26 89 7F 98 3C 26 00 00 00 00 00 00 00 00".ToByteArray()); session.Send(ServerEnterPacket.Confirm()); //session.Send(0xF0, 0x00, 0x1F, 0x78, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00); //session.Send(0x28, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00); //session.Send(ServerEnterPacket.Confirm()); }
public override void Handle(GameSession session, PacketReader packet) { long accountId = packet.ReadLong(); AuthData authData = AuthStorage.GetData(accountId); // Backwards seeking because we read accountId here packet.Skip(-8); HandleCommon(session, packet); Player player = DatabaseManager.GetCharacter(authData.CharacterId); if (player == default) { throw new ArgumentException("Character not found!"); } player.Session = session; session.InitPlayer(player); //session.Send(0x27, 0x01); // Meret market related...? session.Send(BuddyPacket.Initialize()); session.Send(LoginPacket.LoginRequired(accountId)); if (session.Player.Guild != null) { Guild guild = DatabaseManager.GetGuild(session.Player.Guild.Id); session.Send(GuildPacket.UpdateGuild(guild)); session.Send(GuildPacket.MemberJoin(player)); } session.Send(BuddyPacket.LoadList(player)); session.Send(BuddyPacket.EndList(player.BuddyList.Count)); // Meret market //session.Send("6E 00 0B 00 00 00 00 00 00 00 00 00 00 00 00".ToByteArray()); //session.Send("6E 00 0C 00 00 00 00".ToByteArray()); // UserConditionEvent //session.Send("BF 00 00 00 00 00 00".ToByteArray()); // PCBangBonus //session.Send("A7 00 03 00 00 00 00 00 00 00 00 00 00 00 00 00".ToByteArray()); TimeSyncPacket.SetInitial1(); TimeSyncPacket.SetInitial2(); TimeSyncPacket.Request(); session.Send(StatPacket.SetStats(session.FieldPlayer)); // TODO: Grab Hp/Spirit/Stam from last login player.Stats.InitializePools(player.Stats[PlayerStatId.Hp].Max, player.Stats[PlayerStatId.Spirit].Max, player.Stats[PlayerStatId.Stamina].Max); session.SyncTicks(); session.Send(DynamicChannelPacket.DynamicChannel()); session.Send(ServerEnterPacket.Enter(session)); // SendUgc f(0x16), SendCash f(0x09), SendContentShutdown f(0x01, 0x04), SendPvp f(0x0C) PacketWriter pWriter = PacketWriter.Of(SendOp.SYNC_NUMBER); pWriter.WriteByte(); session.Send(pWriter); // 0x112, Prestige f(0x00, 0x07) session.Send(PrestigePacket.Prestige(session.Player)); // Load inventory tabs foreach (InventoryTab tab in Enum.GetValues(typeof(InventoryTab))) { InventoryController.LoadInventoryTab(session, tab); } List <QuestMetadata> questList = QuestMetadataStorage.GetAvailableQuests(player.Levels.Level); // TODO: This logic needs to be refactored when DB is implemented questList.Add(QuestMetadataStorage.GetMetadata(60100000)); // Manually adding "the caravan" for testing purposes foreach (QuestMetadata quest in questList) { session.Player.QuestList.Add(new QuestStatus(quest)); } IEnumerable <List <QuestStatus> > packetCount = SplitList(session.Player.QuestList, 200); // Split the quest list in 200 quests per packet, same way kms do foreach (List <QuestStatus> item in packetCount) { session.Send(QuestPacket.SendQuests(item)); } session.Send(TrophyPacket.WriteTableStart()); List <Trophy> trophyList = new List <Trophy>(session.Player.TrophyData.Values); IEnumerable <List <Trophy> > trophyListPackets = SplitList(trophyList, 60); foreach (List <Trophy> trophy in trophyListPackets) { session.Send(TrophyPacket.WriteTableContent(trophy)); } session.Send(WarehouseInventoryPacket.Count()); // Typically sent after buddylist session.Send(WarehouseInventoryPacket.StartList()); session.Send(WarehouseInventoryPacket.EndList()); session.Send(FurnishingInventoryPacket.StartList()); session.Send(FurnishingInventoryPacket.EndList()); // SendQuest, SendAchieve, SendManufacturer, SendUserMaid session.Send(UserEnvPacket.SetTitles(player)); session.Send(UserEnvPacket.Send04()); session.Send(UserEnvPacket.Send05()); session.Send(UserEnvPacket.Send08()); session.Send(UserEnvPacket.Send09()); session.Send(UserEnvPacket.Send10()); session.Send(UserEnvPacket.Send12()); // SendMeretMarket f(0xC9) session.Send(FishingPacket.LoadAlbum(player)); // SendPvp f(0x16,0x17), ResponsePet f(0x07), 0xF6 // CharacterAbility // E1 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 // Normally, options are only requested for a new character. Since we don't have a database, we'll always requests the users bindings session.Send(KeyTablePacket.RequestDefault()); // TODO - Ask for mouse or kb controls on new character creation. // Commented out since its annoying to click every time //session.Send(KeyTablePacket.AskKeyboardOrMouse()); // Key bindings and skill slots would normally be loaded from a database // If the character is not a new character, this is what we would send // session.Send(KeyTablePacket.SendFullOptions(session.Player.Options)); // SendKeyTable f(0x00), SendGuideRecord f(0x03), GameEvent f(0x00) // SendBannerList f(0x19), SendRoomDungeon f(0x05, 0x14, 0x17) // FieldEntrance session.Send("19 00 00 65 00 00 00 29 7C 7D 01 0C 4D A1 6F 01 0C D3 1A 5F 01 0C EF 03 00 00 01 A2 3C 31 01 0C 3F 0C B7 0D 01 6B 55 5F 01 0C 3A 77 31 01 0C B1 98 BA 01 0C 03 90 5F 01 0C F9 7A 40 01 0C 91 B5 40 01 0C F9 57 31 01 0C 2F C7 BB 0D 01 81 97 7D 01 0C C2 70 5F 01 0C 51 96 40 01 0C B9 38 31 01 0C 41 78 7D 01 0C 65 9D 6F 01 0C 83 51 5F 01 0C 52 73 31 01 0C FF E0 B8 0D 01 11 77 40 01 0C A9 B1 40 01 0C 11 54 31 01 0C DA 6C 5F 01 0C 69 92 40 01 0C D1 34 31 01 0C 7D 99 6F 01 0C 03 13 5F 01 0C 69 6F 31 01 0C 32 88 5F 01 0C 9B 4D 5F 01 0C FF 6F B6 0D 01 29 73 40 01 0C C1 AD 40 01 0C 29 50 31 01 0C 81 8E 40 01 0C E9 30 31 01 0C 09 CE 8C 01 0C 95 95 6F 01 0C 1B 0F 5F 01 0C 4A 84 5F 01 0C B3 49 5F 01 0C 82 6B 31 01 0C 4F 15 BC 0D 01 F9 8C BA 01 00 D9 A9 40 01 0C 41 4C 31 01 0C EF B9 B8 0D 01 99 8A 40 01 0C 21 CA 8C 01 0C 01 AD 6F 01 0C 33 0B 5F 01 0C 99 67 31 01 0C 62 80 5F 01 0C CB 45 5F 01 0C 79 08 9C 01 0C F1 A5 40 01 0C E1 87 7D 01 0C BB 9B 5F 01 0C B1 86 40 01 0C 39 C6 8C 01 0C 7A 7C 5F 01 0C B2 63 31 01 0C 29 85 BA 01 0E 91 04 9C 01 0C 09 A2 40 01 0C 71 44 31 01 0C F9 83 7D 01 0C 1D A9 6F 01 0C D3 97 5F 01 0C C9 82 40 01 0C 51 C2 8C 01 0C 61 BD 40 01 0C C9 5F 31 01 0C 51 9F 7D 01 0C 92 78 5F 01 0C 0F 08 B9 0D 01 A9 00 9C 01 0C 89 40 31 01 0C 11 80 7D 01 0C 35 A5 6F 01 0C BB 1E 5F 01 0C 53 59 5F 01 0C E9 03 00 00 01 22 7B 31 01 0C EB 93 5F 01 0C EA 03 00 00 01 E1 7E 40 01 0C 69 BE 8C 01 0C 79 B9 40 01 0C E1 5B 31 01 0C EB 03 00 00 01 69 9B 7D 01 0C AA 74 5F 01 0C EC 03 00 00 01 ED 03 00 00 01 C1 FC 9B 01 0C EE 03 00 00 01".ToByteArray()); // 0xF0, ResponsePet P(0F 01) // RequestFieldEnter //session.Send("16 00 00 41 75 19 03 00 01 8A 42 0F 00 00 00 00 00 00 C0 28 C4 00 40 03 44 00 00 16 44 00 00 00 00 00 00 00 00 55 FF 33 42 E8 49 01 00".ToByteArray()); session.Send(FieldPacket.RequestEnter(session.FieldPlayer)); // SendUgc: 15 01 00 00 00 00 00 00 00 00 00 00 00 4B 00 00 00 // SendHomeCommand: 00 E1 0F 26 89 7F 98 3C 26 00 00 00 00 00 00 00 00 //session.Send("B9 00 00 E1 0F 26 89 7F 98 3C 26 00 00 00 00 00 00 00 00".ToByteArray()); //session.Send(ServerEnterPacket.Confirm()); //session.Send(0xF0, 0x00, 0x1F, 0x78, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00); //session.Send(0x28, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00); //session.Send(ServerEnterPacket.Confirm()); }
public override void Execute(GameCommandTrigger trigger) { Player player = trigger.Session.Player; // Reset stats to default player.Stats = new(player.Job); player.Stats.AddBaseStats(player, 90); trigger.Session.Send(StatPacket.SetStats(player.FieldPlayer)); trigger.Session.FieldManager.BroadcastPacket(StatPacket.SetStats(player.FieldPlayer), trigger.Session); player.Levels.SetLevel(90); player.Levels.SetPrestigeLevel(100); player.Wallet.Meso.SetAmount(10_000_000_000); // 10B player.Account.Meret.SetAmount(10_000_000_000); // 10B PremiumClubHandler.ActivatePremium(trigger.Session, 2592000); // 30 days in seconds // Stickers for (int i = 1; i < 7; i++) { if (player.ChatSticker.Any(x => x.GroupId == i)) { continue; } trigger.Session.Send(ChatStickerPacket.AddSticker(21100000 + i, i, long.MaxValue)); player.ChatSticker.Add(new((byte)i, long.MaxValue)); } List <int> emotes = SkillMetadataStorage.GetEmotes(); foreach (int emoteId in emotes) { // Broken emotes if (emoteId is >= 90200032 and <= 90200036) { continue; } if (player.Emotes.Contains(emoteId)) { continue; } player.Emotes.Add(emoteId); trigger.Session.Send(EmotePacket.LearnEmote(emoteId)); } List <TitleMetadata> titles = TitleMetadataStorage.GetAll(); foreach (TitleMetadata title in titles) { int titleId = title.Id; if (player.Titles.Contains(titleId)) { continue; } player.Titles.Add(titleId); trigger.Session.Send(UserEnvPacket.AddTitle(titleId)); } DatabaseManager.Characters.Update(player); trigger.Session.Send(NoticePacket.Notice("Done!", NoticeType.Chat)); }
public override void Handle(GameSession session, PacketReader packet) { byte function = packet.ReadByte(); // Unknown what this is for session.ClientTick = packet.ReadInt(); //ClientTicks packet.ReadInt(); // ServerTicks byte segments = packet.ReadByte(); if (segments < 1) { return; } SyncState[] syncStates = new SyncState[segments]; for (int i = 0; i < segments; i++) { syncStates[i] = packet.ReadSyncState(); packet.ReadInt(); // ClientTicks packet.ReadInt(); // ServerTicks } Packet syncPacket = SyncStatePacket.UserSync(session.FieldPlayer, syncStates); session.FieldManager.BroadcastPacket(syncPacket, session); CoordF coord = syncStates[0].Coord.ToFloat(); CoordF closestBlock = Block.ClosestBlock(coord); closestBlock.Z -= Block.BLOCK_SIZE; // Get block under player if (IsCoordSafe(session, syncStates[0].Coord, closestBlock)) { session.Player.SafeBlock = closestBlock; } session.FieldPlayer.Coord = syncStates[0].Coord.ToFloat(); if (IsOutOfBounds(session.FieldPlayer.Coord, session.FieldManager.BoundingBox)) { int currentHp = session.Player.Stats[PlayerStatId.Hp].Current; int fallDamage = currentHp * Math.Clamp(currentHp * 4 / 100 - 1, 0, 25) / 100; // TODO: Create accurate damage model CoordF safeBlock = session.Player.SafeBlock; safeBlock.Z += Block.BLOCK_SIZE + 1; // Without this player will spawn inside the block // for some reason if coord is negative player is teleported one block over, which can result player being stuck inside a block if (session.FieldPlayer.Coord.X < 0) { safeBlock.X -= Block.BLOCK_SIZE; } if (session.FieldPlayer.Coord.Y < 0) { safeBlock.Y -= Block.BLOCK_SIZE; } session.Player.ConsumeHp(fallDamage); session.Send(UserMoveByPortalPacket.Move(session, safeBlock, session.Player.Rotation)); session.Send(StatPacket.UpdateStats(session.FieldPlayer, PlayerStatId.Hp)); session.Send(FallDamagePacket.FallDamage(session, fallDamage)); } // not sure if this needs to be synced here session.Player.Animation = syncStates[0].Animation1; }
private void HandleEquipItem(GameSession session, PacketReader packet) { long itemUid = packet.ReadLong(); string equipSlotStr = packet.ReadUnicodeString(); if (!Enum.TryParse(equipSlotStr, out ItemSlot equipSlot)) { Logger.Warning("Unknown equip slot: " + equipSlotStr); return; } // Remove the item from the users inventory InventoryController.Remove(session, itemUid, out Item item); // Get correct equipped inventory Dictionary <ItemSlot, Item> equippedInventory = session.Player.GetEquippedInventory(item.InventoryTab); if (equippedInventory == null) { Logger.Warning("equippedInventory was null: " + item.InventoryTab); return; } // Move previously equipped item back to inventory if (equippedInventory.Remove(equipSlot, out Item prevItem)) { prevItem.Slot = item.Slot; InventoryController.Add(session, prevItem, false); session.FieldManager.BroadcastPacket(EquipmentPacket.UnequipItem(session.FieldPlayer, prevItem)); } // Handle unequipping pants when equipping dresses // Handle unequipping off-hand when equipping two-handed weapons if (item.IsDress || item.IsTwoHand) { if (equippedInventory.Remove(item.IsDress ? ItemSlot.PA : ItemSlot.LH, out Item prevItem2)) { prevItem2.Slot = -1; if (prevItem == null) { prevItem2.Slot = item.Slot; } InventoryController.Add(session, prevItem2, false); session.FieldManager.BroadcastPacket(EquipmentPacket.UnequipItem(session.FieldPlayer, prevItem2)); } } // Handle unequipping dresses when equipping pants // Handle unequipping two-handed main-hands when equipping off-hand weapons if (item.ItemSlot == ItemSlot.PA || item.ItemSlot == ItemSlot.LH) { ItemSlot prevItemSlot = item.ItemSlot == ItemSlot.PA ? ItemSlot.CL : ItemSlot.RH; if (equippedInventory.ContainsKey(prevItemSlot)) { if (equippedInventory[prevItemSlot] != null && equippedInventory[prevItemSlot].IsDress) { if (equippedInventory.Remove(prevItemSlot, out Item prevItem2)) { prevItem2.Slot = item.Slot; InventoryController.Add(session, prevItem2, false); session.FieldManager.BroadcastPacket(EquipmentPacket.UnequipItem(session.FieldPlayer, prevItem2)); } } } } // Equip new item equippedInventory[equipSlot] = item; session.FieldManager.BroadcastPacket(EquipmentPacket.EquipItem(session.FieldPlayer, item, equipSlot)); if (item.InventoryTab == InventoryTab.Gear) { // TODO - Increase stats based on the item stats itself session.Player.Stats.CritRate.Max += 12; session.Player.Stats.CritRate.Total += 12; session.Player.Stats.MinAtk.Max += 15; session.Player.Stats.MinAtk.Total += 15; session.Player.Stats.MaxAtk.Max += 17; session.Player.Stats.MaxAtk.Total += 17; session.Player.Stats.MagAtk.Max += 15; session.Player.Stats.MagAtk.Total += 15; session.Send(StatPacket.SetStats(session.FieldPlayer)); } }
public override void Handle(GameSession session, PacketReader packet) { long accountId = packet.ReadLong(); AuthData authData = DatabaseManager.AuthData.GetByAccountId(accountId); Player dbPlayer = DatabaseManager.Characters.FindPlayerById(authData.OnlineCharacterId, session); // Backwards seeking because we read accountId here packet.Skip(-8); HandleCommon(session, packet); session.InitPlayer(dbPlayer); Player player = session.Player; player.BuddyList = GameServer.BuddyManager.GetBuddies(player.CharacterId); player.Mailbox = GameServer.MailManager.GetMails(player.CharacterId); GameServer.PlayerManager.AddPlayer(player); GameServer.BuddyManager.SetFriendSessions(player); // Only send buddy login notification if player is not changing channels if (!player.IsMigrating) { player.UpdateBuddies(); } if (player.GuildId != 0) { Guild guild = GameServer.GuildManager.GetGuildById(player.GuildId); player.Guild = guild; GuildMember guildMember = guild.Members.First(x => x.Id == player.CharacterId); guildMember.Player.Session = session; player.GuildMember = guildMember; session.Send(GuildPacket.UpdateGuild(guild)); guild.BroadcastPacketGuild(GuildPacket.MemberJoin(player)); guild.BroadcastPacketGuild(GuildPacket.MemberLoggedIn(player), session); } player.IsMigrating = false; //session.Send(0x27, 0x01); // Meret market related...? session.Send(MushkingRoyaleSystemPacket.LoadStats(player.Account.MushkingRoyaleStats)); session.Send(MushkingRoyaleSystemPacket.LoadMedals(player.Account)); player.GetUnreadMailCount(); session.Send(BuddyPacket.Initialize()); session.Send(BuddyPacket.LoadList(player.BuddyList)); session.Send(BuddyPacket.EndList(player.BuddyList.Count)); // Meret market //session.Send("6E 00 0B 00 00 00 00 00 00 00 00 00 00 00 00".ToByteArray()); //session.Send("6E 00 0C 00 00 00 00".ToByteArray()); // UserConditionEvent //session.Send("BF 00 00 00 00 00 00".ToByteArray()); // PCBangBonus //session.Send("A7 00 03 00 00 00 00 00 00 00 00 00 00 00 00 00".ToByteArray()); session.Send(TimeSyncPacket.SetInitial1()); session.Send(TimeSyncPacket.SetInitial2()); session.Send(StatPacket.SetStats(session.Player.FieldPlayer)); // session.Send(StatPacket.SetStats(session.Player.FieldPlayer)); // Second packet is meant to send the stats initialized, for now we'll just send the first one session.Player.ClientTickSyncLoop(); session.Send(DynamicChannelPacket.DynamicChannel(short.Parse(ConstantsMetadataStorage.GetConstant("ChannelCount")))); session.Send(ServerEnterPacket.Enter(session)); session.Send(UgcPacket.Unknown22()); session.Send(CashPacket.Unknown09()); // SendContentShutdown f(0x01, 0x04) session.Send(PvpPacket.Mode0C()); session.Send(SyncNumberPacket.Send()); session.Send(SyncValuePacket.SetSyncValue(120000)); // unknown what this value means session.Send(PrestigePacket.SetLevels(player)); session.Send(PrestigePacket.WeeklyMissions()); // Load inventory tabs foreach (InventoryTab tab in Enum.GetValues(typeof(InventoryTab))) { player.Inventory.LoadInventoryTab(session, tab); } if (player.Account.HomeId != 0) { Home home = GameServer.HomeManager.GetHomeById(player.Account.HomeId); player.Account.Home = home; session.Send(WarehouseInventoryPacket.StartList()); int counter = 0; foreach (KeyValuePair <long, Item> kvp in home.WarehouseInventory) { session.Send(WarehouseInventoryPacket.Load(kvp.Value, ++counter)); } session.Send(WarehouseInventoryPacket.EndList()); session.Send(FurnishingInventoryPacket.StartList()); foreach (Cube cube in home.FurnishingInventory.Values.Where(x => x.Item != null)) { session.Send(FurnishingInventoryPacket.Load(cube)); } session.Send(FurnishingInventoryPacket.EndList()); } session.Send(QuestPacket.StartList()); session.Send(QuestPacket.Packet1F()); session.Send(QuestPacket.Packet20()); IEnumerable <List <QuestStatus> > packetCount = player.QuestData.Values.ToList().SplitList(200); // Split the quest list in 200 quests per packet foreach (List <QuestStatus> item in packetCount) { session.Send(QuestPacket.SendQuests(item)); } session.Send(QuestPacket.EndList()); session.Send(TrophyPacket.WriteTableStart()); List <Trophy> trophyList = new(player.TrophyData.Values); IEnumerable <List <Trophy> > trophyListPackets = trophyList.SplitList(60); foreach (List <Trophy> trophy in trophyListPackets) { session.Send(TrophyPacket.WriteTableContent(trophy)); } // SendQuest, SendAchieve, SendManufacturer, SendUserMaid session.Send(UserEnvPacket.SetTitles(player)); session.Send(UserEnvPacket.Send04()); session.Send(UserEnvPacket.Send05()); session.Send(UserEnvPacket.UpdateLifeSkills(player.GatheringCount)); session.Send(UserEnvPacket.Send09()); session.Send(UserEnvPacket.Send10()); session.Send(UserEnvPacket.Send12()); session.Send(MeretMarketPacket.ModeC9()); session.Send(FishingPacket.LoadAlbum(player)); session.Send(PvpPacket.Mode16()); session.Send(PvpPacket.Mode17()); session.Send(ResponsePetPacket.Mode07()); // LegionBattle (0xF6) // CharacterAbility // E1 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 // Key bindings and skill slots would normally be loaded from a database // If the character is not a new character, this is what we would send session.Send(KeyTablePacket.SendFullOptions(player.GameOptions)); if (player.MapId == (int)Map.UnknownLocation) // tutorial map { session.Send(KeyTablePacket.AskKeyboardOrMouse()); } // SendKeyTable f(0x00), SendGuideRecord f(0x03), GameEvent f(0x00) // SendBannerList f(0x19), SendRoomDungeon f(0x05, 0x14, 0x17) session.Send(DungeonListPacket.DungeonList()); // 0xF0, ResponsePet P(0F 01) // RequestFieldEnter //session.Send("16 00 00 41 75 19 03 00 01 8A 42 0F 00 00 00 00 00 00 C0 28 C4 00 40 03 44 00 00 16 44 00 00 00 00 00 00 00 00 55 FF 33 42 E8 49 01 00".ToByteArray()); session.Send(RequestFieldEnterPacket.RequestEnter(player.FieldPlayer)); Party party = GameServer.PartyManager.GetPartyByMember(player.CharacterId); if (party != null) { player.Party = party; party.BroadcastPacketParty(PartyPacket.LoginNotice(player), session); session.Send(PartyPacket.Create(party, false)); } // SendUgc: 15 01 00 00 00 00 00 00 00 00 00 00 00 4B 00 00 00 // SendHomeCommand: 00 E1 0F 26 89 7F 98 3C 26 00 00 00 00 00 00 00 00 player.TimeSyncLoop(); session.Send(TimeSyncPacket.SetSessionServerTick(0)); //session.Send("B9 00 00 E1 0F 26 89 7F 98 3C 26 00 00 00 00 00 00 00 00".ToByteArray()); session.Send(ServerEnterPacket.Confirm()); //session.Send(0xF0, 0x00, 0x1F, 0x78, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00); //session.Send(0x28, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00); }