예제 #1
0
    private static void HandleUpdateCatalysts(GameSession session, PacketReader packet)
    {
        long itemUid     = packet.ReadLong();
        bool addCatalyst = packet.ReadBool();

        if (!session.Player.Inventory.HasItem(itemUid) && !session.Player.Inventory.ItemIsEquipped(itemUid))
        {
            return;
        }

        ItemEnchant itemEnchant = session.Player.ItemEnchant;

        if (itemEnchant is null)
        {
            return;
        }

        if (!itemEnchant.UpdateAdditionalCatalysts(itemUid, addCatalyst))
        {
            EnchantHelper.ExcessCatalystError(session, itemEnchant);
            return;
        }

        session.Send(ItemEnchantPacket.UpdateCharges(itemEnchant));
    }
예제 #2
0
    private static void SetEnchantStats(GameSession session, ItemEnchant itemEnchantStats, Item item)
    {
        Dictionary <StatAttribute, ItemStat> statDiff = GetEnchantStatDiff(item.Stats.Enchants, itemEnchantStats.Stats);

        foreach (ItemStat stat in itemEnchantStats.Stats.Values)
        {
            if (!item.Stats.Enchants.ContainsKey(stat.ItemAttribute))
            {
                item.Stats.Enchants[stat.ItemAttribute] = new BasicStat(stat.ItemAttribute, stat.Rate, StatAttributeType.Rate);
                continue;
            }
            item.Stats.Enchants[stat.ItemAttribute].Flat = stat.Flat;
            item.Stats.Enchants[stat.ItemAttribute].Rate = stat.Rate;
        }
        item.EnchantLevel++;
        item.EnchantExp = 0;
        item.Charges   -= itemEnchantStats.Rates.ChargesAdded;
        if (item.EnchantLevel > 11)
        {
            string message = $"3,{item.Uid},{ChatLinkType.Enchant},{session.Player.Name}"; //unk what 3 is
            MapleServer.BroadcastPacketAll(ItemLinkPacket.SendLinkItem(new()
            {
                item
            }));
            MapleServer.BroadcastPacketAll(ChatPacket.Send(session.Player, message, ChatType.ItemEnchant));
        }

        session.Send(ItemEnchantPacket.EnchantSuccess(item, statDiff.Values.ToList()));
        //TODO: If item is equipped, update stats
    }
예제 #3
0
    public static void ExcessCatalystError(GameSession session, ItemEnchant itemEnchant)
    {
        int npcId = itemEnchant.Type switch
        {
            EnchantType.Ophelia => 11000508,
            _ => 11000510
        };
        ScriptMetadata scriptMetadata = ScriptMetadataStorage.GetNpcScriptMetadata(npcId);
        NpcScript      npcScript      = scriptMetadata?.NpcScripts.FirstOrDefault(x => x.Id == 31);

        if (npcScript is null)
        {
            return;
        }

        Script   script = ScriptLoader.GetScript($"Npcs/{npcId}", session);
        DynValue excessCatalystFunction = script.RunFunction("getExcessCatalystEventId");

        if (excessCatalystFunction is null)
        {
            return;
        }

        int eventId = (int)excessCatalystFunction.Number;

        if (eventId == 0)
        {
            return;
        }

        HandleNpcTalkEventType(session, npcScript, eventId);
    }
예제 #4
0
    public static void TalkError(GameSession session, ItemEnchant itemEnchant)
    {
        int npcId = itemEnchant.Type switch
        {
            EnchantType.Ophelia => 11000508,
            _ => 11000510
        };
        ScriptMetadata scriptMetadata = ScriptMetadataStorage.GetNpcScriptMetadata(npcId);
        NpcScript      npcScript      = scriptMetadata?.NpcScripts.FirstOrDefault(x => x.Id == 31);

        if (npcScript is null)
        {
            return;
        }

        Script script  = ScriptLoader.GetScript($"Npcs/{npcId}", session);
        int    eventId = (int)script.RunFunction("getProcessEventId", PlayerHasIngredients(itemEnchant, session.Player.Inventory),
                                                 PlayerHasRequiredCatalysts(itemEnchant)).Number;

        if (eventId == 0)
        {
            return;
        }

        HandleNpcTalkEventType(session, npcScript, eventId);
    }
예제 #5
0
    private static void HandlePeachyEnchant(GameSession session, PacketReader packet)
    {
        long itemUid = packet.ReadLong();

        IInventory inventory = session.Player.Inventory;
        Item       item      = inventory.GetFromInventoryOrEquipped(itemUid);

        if (item is null)
        {
            return;
        }

        ItemEnchant itemEnchantStats = session.Player.ItemEnchant;

        if (itemEnchantStats.Level != item.EnchantLevel && itemEnchantStats.ItemUid != item.Uid)
        {
            itemEnchantStats = GetEnchantInfo(item, EnchantType.Peachy);
        }

        // Check if player has enough ingredients
        if (!EnchantHelper.PlayerHasIngredients(itemEnchantStats, inventory) || !EnchantHelper.PlayerHasRequiredCatalysts(itemEnchantStats))
        {
            session.Send(ItemEnchantPacket.Notice((short)ItemEnchantError.NotEnoughMaterials));
            EnchantHelper.TalkError(session, itemEnchantStats);
            return;
        }

        foreach (EnchantIngredient ingredient in itemEnchantStats.Ingredients)
        {
            inventory.ConsumeByTag(session, ingredient.Tag.ToString(), ingredient.Amount);
        }

        foreach (long catalystUids in itemEnchantStats.CatalystItemUids)
        {
            inventory.ConsumeItem(session, catalystUids, 1);
        }

        int neededEnchants = GetNeededEnchantExp(item.EnchantLevel);
        int expGained      = (int)Math.Ceiling((double)(10000 / neededEnchants));

        item.EnchantExp += expGained;
        if (item.EnchantExp >= 10000)
        {
            item.EnchantExp = 0;
            SetEnchantStats(session, itemEnchantStats, item);
        }

        itemEnchantStats.Success = true;
        itemEnchantStats.Level++;
        itemEnchantStats.CatalystItemUids.Clear();
        session.Send(ItemEnchantPacket.UpdateExp(item));
    }
예제 #6
0
    private static void HandleOpheliaEnchant(GameSession session, PacketReader packet)
    {
        long itemUid = packet.ReadLong();

        IInventory inventory = session.Player.Inventory;
        Item       item      = inventory.GetFromInventoryOrEquipped(itemUid);

        if (item is null)
        {
            return;
        }

        ItemEnchant itemEnchantStats = session.Player.ItemEnchant;

        if (itemEnchantStats.Level != item.EnchantLevel && itemEnchantStats.ItemUid != item.Uid)
        {
            itemEnchantStats = GetEnchantInfo(item, EnchantType.Ophelia);
        }

        // Check if player has enough ingredients
        if (!EnchantHelper.PlayerHasIngredients(itemEnchantStats, inventory) || !EnchantHelper.PlayerHasRequiredCatalysts(itemEnchantStats))
        {
            session.Send(ItemEnchantPacket.Notice((short)ItemEnchantError.NotEnoughMaterials));
            EnchantHelper.TalkError(session, itemEnchantStats);
            return;
        }

        foreach (EnchantIngredient ingredient in itemEnchantStats.Ingredients)
        {
            inventory.ConsumeByTag(session, ingredient.Tag.ToString(), ingredient.Amount);
        }

        foreach (long catalystUids in itemEnchantStats.CatalystItemUids)
        {
            inventory.ConsumeItem(session, catalystUids, 1);
        }

        Random random       = Random.Shared;
        double randomResult = random.NextDouble();

        if (itemEnchantStats.Rates.TotalSuccessRate() < (float)(randomResult * 100))
        {
            FailEnchant(session, itemEnchantStats, item);
            itemEnchantStats.Success = false;
            return;
        }

        // Enchant success
        itemEnchantStats.Success = true;
        itemEnchantStats.Level++;
        SetEnchantStats(session, itemEnchantStats, item);
    }
예제 #7
0
    public static PacketWriter EnchantFail(Item item, ItemEnchant enchantInfo)
    {
        PacketWriter pWriter = PacketWriter.Of(SendOp.ItemEnchant);

        pWriter.Write(ItemEnchantPacketMode.EnchantFail);
        pWriter.WriteLong(item.Uid);
        pWriter.WriteItem(item);
        pWriter.WriteInt();
        pWriter.WriteInt();
        pWriter.WriteLong();
        pWriter.WriteInt(enchantInfo.PityCharges);
        return(pWriter);
    }
예제 #8
0
    public static bool PlayerHasIngredients(ItemEnchant itemEnchantStats, IInventory inventory)
    {
        foreach (EnchantIngredient ingredient in itemEnchantStats.Ingredients)
        {
            IReadOnlyCollection <Item> ingredientTotal = inventory.GetAllByTag(ingredient.Tag.ToString());
            if (ingredientTotal.Sum(x => x.Amount) < ingredient.Amount)
            {
                return(false);
            }
        }

        return(true);
    }
예제 #9
0
    public static PacketWriter UpdateCharges(ItemEnchant itemEnchant)
    {
        PacketWriter pWriter = PacketWriter.Of(SendOp.ItemEnchant);

        pWriter.Write(ItemEnchantPacketMode.UpdateCharges);
        pWriter.WriteInt(itemEnchant.Rates.ChargesAdded);
        pWriter.WriteInt(itemEnchant.CatalystItemUids.Count);
        pWriter.WriteInt(itemEnchant.CatalystItemUids.Count);
        foreach (long uid in itemEnchant.CatalystItemUids)
        {
            pWriter.WriteLong(uid);
        }
        WriteEnchantRates(pWriter, itemEnchant.Rates);
        return(pWriter);
    }
예제 #10
0
    private static void HandleUpdateCharges(GameSession session, PacketReader packet)
    {
        int         chargeCount = packet.ReadInt();
        ItemEnchant itemEnchant = session.Player.ItemEnchant;

        Player player = session.Player;
        Item   item   = player.Inventory.GetFromInventoryOrEquipped(itemEnchant.ItemUid);

        if (item == null || item.Charges < chargeCount)
        {
            return;
        }

        player.ItemEnchant.UpdateCharges(chargeCount);

        session.Send(ItemEnchantPacket.UpdateCharges(session.Player.ItemEnchant));
    }
예제 #11
0
    public static PacketWriter BeginEnchant(EnchantType type, Item item, ItemEnchant enchantInfo, Dictionary <StatAttribute, ItemStat> stats)
    {
        PacketWriter pWriter = PacketWriter.Of(SendOp.ItemEnchant);

        pWriter.Write(ItemEnchantPacketMode.BeginEnchant);
        pWriter.Write(type);
        pWriter.WriteLong(item.Uid);
        pWriter.WriteByte((byte)enchantInfo.Ingredients.Count);
        foreach (EnchantIngredient ingredient in enchantInfo.Ingredients)
        {
            pWriter.WriteInt();
            pWriter.Write(ingredient.Tag);
            pWriter.WriteInt(ingredient.Amount);
        }

        pWriter.WriteShort();
        pWriter.WriteInt(enchantInfo.Stats.Count);
        foreach (ItemStat stat in stats.Values)
        {
            pWriter.Write(stat.ItemAttribute);
            pWriter.WriteInt(stat.Flat);
            pWriter.WriteFloat(stat.Rate);
        }

        if (type is EnchantType.Ophelia)
        {
            WriteEnchantRates(pWriter, enchantInfo.Rates);
            pWriter.WriteLong();
            pWriter.WriteLong();
            pWriter.WriteByte(1);
        }

        // Item copies required
        if (type is EnchantType.Ophelia or EnchantType.Peachy)
        {
            pWriter.WriteInt(enchantInfo.CatalystAmountRequired > 0 ? item.Id : 0);
            pWriter.WriteShort((short)(enchantInfo.CatalystAmountRequired > 0 ? item.Rarity : 0));
            pWriter.WriteInt(enchantInfo.CatalystAmountRequired > 0 ? item.Amount : 0);
        }
        return(pWriter);
    }
예제 #12
0
 private static void FailEnchant(GameSession session, ItemEnchant itemEnchantStats, Item item)
 {
     item.Charges -= itemEnchantStats.Rates.ChargesAdded;
     item.Charges += itemEnchantStats.PityCharges;
     session.Send(ItemEnchantPacket.EnchantFail(item, itemEnchantStats));
 }
예제 #13
0
 public static bool PlayerHasRequiredCatalysts(ItemEnchant itemEnchantStats)
 {
     return(itemEnchantStats.CatalystAmountRequired <= itemEnchantStats.CatalystItemUids.Count);
 }