public static bool HasSpace(Character pChar, int nItemID, short nAmount) { var nTI = ItemConstants.GetInventoryType(nItemID); if (nTI == InventoryType.Equip) { if (pChar.InventoryEquip.GetFreeSlot() > 0) { return(true); } } else { var inv = GetInventory(pChar, nTI); if (inv.GetFreeSlot() > 0) { return(true); } // determine if item can be merged in with existing slot { var item = inv.Get(inv.FindItemSlot(nItemID)); if (item?.nNumber < nAmount + item?.SlotMax) { return(true); } } } return(false); }
public static MapleItem CreateItem(int itemId, string source, short quantity = 1, bool randomStats = false) { MapleInventoryType type = ItemConstants.GetInventoryType(itemId); if (type == MapleInventoryType.Equip) { WzEquip wzInfo = DataBuffer.GetEquipById(itemId); if (wzInfo != null) { MapleEquip equip = new MapleEquip(itemId, source); equip.SetDefaultStats(wzInfo, randomStats); return(equip); } } else if (type != MapleInventoryType.Undefined) { WzItem wzInfo = DataBuffer.GetItemById(itemId); if (wzInfo != null) { if (wzInfo.SlotMax > 0 && quantity > wzInfo.SlotMax) { quantity = (short)wzInfo.SlotMax; } MapleItem item = new MapleItem(itemId, source, quantity); return(item); } } return(null); }
public static GW_ItemSlotEquip CreateNormalStatEquip(int nItemID, long liCashItemSN = 0) { if (ItemConstants.GetInventoryType(nItemID) != InventoryType.Equip) { return(null); } var pItem = new GW_ItemSlotEquip(nItemID); pItem.niSTR = (short)pItem.EquipTemplate.incSTR; pItem.niDEX = (short)pItem.EquipTemplate.incDEX; pItem.niINT = (short)pItem.EquipTemplate.incINT; pItem.niLUK = (short)pItem.EquipTemplate.incLUK; pItem.niMaxHP = (short)pItem.EquipTemplate.incMHP; pItem.niMaxMP = (short)pItem.EquipTemplate.incMMP; pItem.niPAD = (short)pItem.EquipTemplate.incPAD; pItem.niMAD = (short)pItem.EquipTemplate.incMAD; pItem.niPDD = (short)pItem.EquipTemplate.incPDD; pItem.niMDD = (short)pItem.EquipTemplate.incMDD; pItem.niACC = (short)pItem.EquipTemplate.incACC; pItem.niEVA = (short)pItem.EquipTemplate.incEVA; pItem.niSpeed = (short)pItem.EquipTemplate.incSpeed; pItem.niJump = (short)pItem.EquipTemplate.incJump; FinishEquip(pItem, liCashItemSN); return(pItem); }
public static void UnEquip(Character pChar, short slotFrom, short slotTo) { //20:40:35[INFO] Recv[CP_UserChangeSlotPositionRequest] [4D 00] [1D A8 02 01] [01] [B3 FB] [01 00] [FF FF] //20:40:38[INFO] Recv[CP_UserChangeSlotPositionRequest] [4D 00] [7B B3 02 01] [01] [B3 FB] [01 00] [FF FF] var srcEquipInv = GetInventory(pChar, slotFrom); var source = srcEquipInv.GetKvp(slotFrom); if (slotTo != 0) //Not dropping { if (!pChar.InventoryEquip.IsFreeSlot(slotTo)) { return; // PE } } if (!srcEquipInv.Remove(slotFrom)) { return; // false means they passed an empty slot } var pItem = source.Value; if (-slotFrom == (int)BodyPart.BP_SADDLE || -slotFrom == (int)BodyPart.BP_TAMINGMOB) { pChar.Buffs.Remove(pChar.Stats.SecondaryStats.rRideVehicle); } else { // taming stuff cant have option skills pChar.Skills.ModifyOptionSkills(pItem, false); } if (slotTo == 0) //Dropping Item { pChar.Modify.Inventory(ctx => { ctx.Remove(InventoryType.Equip, slotFrom); }); if (ItemConstants.GetInventoryType(pItem.nItemID) == InventoryType.Equip) { CDropFactory.CreateDropItem(pChar.Field, pChar.Position.CurrentXY, pChar.dwId, pItem); } else { //Should never happen???? pChar.SendMessage($"You unequipped and dropped a non-equip item. Please report to staff: {pItem.nItemID}"); } } else //Unequip to inventory { pChar.InventoryEquip.Add(slotTo, source.Value); pChar.Modify.Inventory(ctx => { ctx.Move(InventoryType.Equip, slotFrom, slotTo); }); } }
public void UseLotteryItem(short nPOS, int nItemID) { if (Parent.Stats.nHP <= 0) { return; } var pItemRaw = InventoryManipulator.GetItem(Parent, ItemConstants.GetInventoryType(nItemID), nPOS); // TODO determine if we can hardcode the inventory type var itemResult = MasterManager.CreateItem(RandomBoxes.GetRandom(nItemID)); if (itemResult != null && pItemRaw is GW_ItemSlotBundle pItem) { if (InventoryManipulator.CountFreeSlots(Parent, InventoryType.Equip) > 0 && InventoryManipulator.CountFreeSlots(Parent, InventoryType.Consume) > 0) { InventoryManipulator.RemoveFrom(Parent, pItemRaw.InvType, nPOS); InventoryManipulator.InsertInto(Parent, itemResult); } else { Parent.SendMessage("Please make some room in your inventory."); } } else { Parent.SendMessage("This item has not been implemented yet. If you believe this to be an error, please report it on the discord server."); } }
protected GW_ItemSlotBase(int nItemID) { this.nItemID = nItemID; InvType = ItemConstants.GetInventoryType(nItemID); IsRechargeable = ItemConstants.IsRechargeableItem(nItemID); IsArrow = ItemConstants.IsArrow(nItemID); }
private static void SellItem(Character pChar, short nSlot, int nItemId, short nCount) { var pItem = InventoryManipulator.GetItem(pChar, ItemConstants.GetInventoryType(nItemId), nSlot); if (pItem is null) { pChar.SendMessage("Trying to sell null item."); pChar.SendPacket(CPacket.CShopDlg.ShopResult(ShopRes.SellIncorrectRequest)); return; } if (pItem.CashItem || pItem.NotSale) { pChar.SendMessage("Cannot trade cash items."); return; } var nCostPerItem = pItem.Template.Price; nCount = ItemConstants.is_treat_singly(nItemId) ? (short)1 : nCount; var nFinalCost = nCostPerItem * nCount; if (pItem.IsRechargeable) { var dUnitPrice = ((ConsumeItemTemplate)pItem.Template).UnitPrice; nFinalCost += (int)Math.Floor(dUnitPrice * pItem.nNumber); } if (pItem is GW_ItemSlotBundle && !pItem.IsRechargeable) { if (pItem.nNumber < nCount) { pChar.SendMessage("Trying to sell more than you possess."); pChar.SendPacket(CPacket.CShopDlg.ShopResult(ShopRes.SellIncorrectRequest)); return; } if (nCount <= 0) { pChar.SendMessage("Trying to sell negative amount."); pChar.SendPacket(CPacket.CShopDlg.ShopResult(ShopRes.SellIncorrectRequest)); return; } } else { nCount = -1; } pChar.SendPacket(CPacket.CShopDlg.ShopResult(ShopRes.SellSuccess)); //pChar.SendMessage("final price: " + nFinalCost); InventoryManipulator.RemoveFrom(pChar, pItem.InvType, nSlot, nCount); pChar.Modify.GainMeso(nFinalCost, false); }
public void OnLostQuestItem(CInPacket p, short nQuestID) { var nLostCount = p.Decode4(); var pAct = MasterManager.QuestTemplates[nQuestID].StartAct; if (pAct is null) { return; // invalid quest ID } if (nLostCount <= 0 || pAct.Items.Length <= 0) { return; // TODO trigger AB, close socket } var aLostItem = p.DecodeIntArray(nLostCount); foreach (var item in pAct.Items) { if (!aLostItem.Contains(item.Item.ItemID)) { continue; // TODO trigger AB? } if (ItemConstants.GetInventoryType(item.Item.ItemID) == InventoryType.Equip) { Parent.SendMessage("Not currently supported. Check again later."); return; // TODO } if (!MasterManager.ItemTemplates[item.Item.ItemID]?.Quest ?? true) { continue; } if (InventoryManipulator.HasSpace(Parent, item.Item.ItemID, (short)item.Item.Count)) { var itemToAdd = MasterManager.CreateItem(item.Item.ItemID); itemToAdd.nNumber = (short)item.Item.Count; InventoryManipulator.InsertInto(Parent, itemToAdd); } else { // TODO proper response packet Parent.SendMessage("Please make space in your inventory."); return; } } // TODO // if ( aChangedItem.a && *(aChangedItem.a - 1) > 0u ) // CUser::PostQuestEffect(&v16->vfptr, 1, &aChangedItem, 0, 0); }
public static GW_ItemSlotBase CreateItem(int nItemID, bool bRandStats = true) { if (nItemID <= 0) { return(null); } // TODO test the below if (ItemConstants.GetInventoryType(nItemID) != InventoryType.Equip) { GW_ItemSlotBase item; if (ItemConstants.IsPet(nItemID)) { item = new GW_ItemSlotPet(nItemID); ((GW_ItemSlotPet)item).nRemainLife = 7776000; } else { item = new GW_ItemSlotBundle(nItemID); } if (item.Template is null) { throw new ArgumentOutOfRangeException(nameof(nItemID), "Doesn't exist in data files."); } if (ItemConstants.IsRechargeableItem(item.nItemID)) { item.nNumber = (short)item.Template.SlotMax; } else { item.nNumber = 1; } item.tDateExpire = DateTime.MaxValue; return(item); } if (bRandStats) { return(CreateVariableStatEquip(nItemID)); } return(CreateNormalStatEquip(nItemID)); }
// TODO figure out somewhere else for the below functions to live public static AbstractItemTemplate ItemTemplate(int nItemID) { switch (ItemConstants.GetInventoryType(nItemID)) { case InventoryType.Equip: return(EquipTemplates[nItemID]); case InventoryType.Cash: case InventoryType.Consume: case InventoryType.Etc: case InventoryType.Install: case InventoryType.Special: return(ItemTemplates[nItemID]); default: throw new NullReferenceException("Unable to find a template for item with item ID: " + nItemID); } }
public static bool HasSpace(Character pChar, int[] items) { var map = new Dictionary <InventoryType, int>(); foreach (var item in items) { var nTI = ItemConstants.GetInventoryType(item); if (map.ContainsKey(nTI)) { map[nTI]++; } else { map.Add(nTI, 1); } } return(HasSpace(pChar, map)); }
/// <summary> /// Removes items that aren't in the cached data. /// Note: Must be called after all game data has been cached. /// </summary> public void PurgeInvalidItems() { var entriesToRemove = new List <int>(); foreach (var mob in this) { if (MasterManager.MobTemplates[mob.MobID] is null) { entriesToRemove.Add(mob.MobID); } else { var dropsToKeep = new List <DropStruct>(); foreach (var drop in mob.Drops) { if (ItemConstants.GetInventoryType(drop.ItemID) == Common.Types.InventoryType.Equip) { if (MasterManager.EquipTemplates[drop.ItemID] is null) { continue; } } else { if (MasterManager.ItemTemplates[drop.ItemID] is null) { continue; } } dropsToKeep.Add(drop); } mob.Drops = dropsToKeep; } } foreach (var entry in entriesToRemove) { Remove(entry); } Log.Info("Drops: " + Count); }
public override void Execute(CommandCtx ctx) { var itemId = ctx.NextInt(); var sCount = !ctx.Empty ? ctx.NextString() : null; var nCount = 1; if (sCount is object) { if (!int.TryParse(sCount, out nCount)) { ctx.Character.SendMessage("Unable to parse count."); return; } } var character = ctx.Character; var nInvType = ItemConstants.GetInventoryType(itemId); if (InventoryManipulator.CountFreeSlots(character, nInvType) > 0) { var item = MasterManager.CreateItem(itemId); if (item is null) { return; } if (item is GW_ItemSlotBundle isb) { isb.nNumber = (short)Math.Min(nCount, item.SlotMax); } InventoryManipulator.InsertInto(character, item); character.SendPacket(CPacket.DropPickUpMessage_Item(itemId, nCount, true)); } }
public void PickUp(Character pChar, int dwDropId, short pX, short pY, bool bByPet = false) { var pDrop = this[dwDropId]; if (pDrop is null) { return; } switch (pDrop.DropOwnType) { case DropOwnType.PartyOwn when pChar.Party?.PartyID != pDrop.DropOwnerID: case DropOwnType.UserOwn when pChar.dwId != pDrop.DropOwnerID: pChar.SendMessage("Trying to pick up a drop that doesn't belong to you."); return; } if (pDrop.Item != null) { if (InventoryManipulator.CountFreeSlots(pChar, ItemConstants.GetInventoryType(pDrop.Item.nItemID)) <= 0) { return; } } if (bByPet) { if (Constants.MULTIPET_ACTIVATED) { throw new NotImplementedException(); // since we arent checking multiple pet equip slots } if (pDrop.bIsMoney == 1) { if (InventoryManipulator.GetItem(pChar, BodyPart.BP_PETABIL_MESO, true) is null) { return; } } else { if (InventoryManipulator.GetItem(pChar, BodyPart.BP_PETABIL_ITEM, true) is null) { return; } } pDrop.nLeaveType = DropLeaveType.PetPickup; } else { pDrop.nLeaveType = DropLeaveType.UserPickup; } pDrop.OwnerCharId = pChar.dwId; if (pDrop.bIsMoney > 0) { pChar.Modify.GainMeso(pDrop.nMesoVal); } else { if (pDrop.Item.Template is CashItemTemplate itemDataTemplate) { if (itemDataTemplate.Max > 0 && InventoryManipulator.ContainsItem(pChar, pDrop.ItemId, (short)itemDataTemplate.Max)) { pChar.SendMessage("Can't hold anymore of this item.."); return; } } if (!Field.TryDropPickup(pChar, pDrop)) { return; } pChar.SendPacket(CPacket.DropPickUpMessage_Item(pDrop.ItemId, pDrop.Item.nNumber, false)); if (pDrop.Item.Template.PickupMessage.Length > 0) { pChar.SendMessage(pDrop.Item.Template.PickupMessage); } } Remove(dwDropId); }
public void RemoveFrom(int itemId, short slot, short amount = 1) => InventoryManipulator.RemoveFrom(Character, ItemConstants.GetInventoryType(itemId), slot, amount);
public bool CheckDemand(short nQuestID, int dwNpcTemplateID, int nAct) { // TODO proper response codes var pQuest = MasterManager.QuestTemplates[nQuestID]; var pDemand = nAct == 0 ? pQuest.StartDemand : pQuest.EndDemand; if (pDemand is null) { return(true); // no requirements } var correctNpc = nAct == 0 ? pQuest.StartNPC : pQuest.EndNPC; if (correctNpc != 0 && correctNpc != dwNpcTemplateID) { return(false); } switch (nAct) { case 0 when this[nQuestID] is null: return(true); case 1 when this[nQuestID] is null: case 1 when this[nQuestID].nState == QuestActType.NotStarted: case 0 when this[nQuestID].nState == QuestActType.QuestAccept: return(false); default: if (this[nQuestID].IsComplete) { return(false); } break; } if (Parent.Stats.nLevel < pDemand.LevelMin) { return(false); } if (Parent.Stats.nPOP < pDemand.Pop) { return(false); } if (pQuest.Start > DateTime.MinValue && pQuest.Start.SecondsSinceStart() < 0) { return(false); } // hmm the client is still allowing some quests that have an end date and max level to be triggered... //if (pQuest.End > DateTime.MinValue && pQuest.End.SecondsSinceStart() > 0) return false; //if (pDemand.LevelMax != 0 && Parent.Stats.nLevel > pDemand.LevelMax) return false; if (pDemand.SubJobFlags != 0 && Parent.Stats.nSubJob != pDemand.SubJobFlags) { return(false); } if (pDemand.Job.Length > 0 && pDemand.Job.All(job => job != Parent.Stats.nJob)) { return(false); } foreach (var item in pDemand.DemandItem) { if (ItemConstants.GetInventoryType(item.ItemID) == InventoryType.Equip) { if (InventoryManipulator.ItemEquipped(Parent, item.ItemID)) { continue; } } if (!InventoryManipulator.ContainsItem(Parent, item.ItemID, (short)item.Count)) { return(false); } } if (pDemand.EquipAllNeed.Any( item => !InventoryManipulator.ItemEquipped(Parent, item))) { return(false); } if (pDemand.EquipSelectNeed.Length > 0 && pDemand.EquipSelectNeed.All( // TODO verify item => !InventoryManipulator.ItemEquipped(Parent, item))) { return(false); } foreach (var quest in pDemand.DemandQuest) { if (quest.State == 0 && !Contains(quest.QuestID)) { return(false); } if ((QuestActType)quest.State != this[quest.QuestID].nState) { return(false); } } foreach (var skill in pDemand.DemandSkill) { if (skill.Acquire == 0 && Parent.Skills[skill.SkillID]?.nSLV != 0) { return(false); } if (Parent.Skills[skill.SkillID].nSLV == 0) { return(false); } } foreach (var mob in pDemand.DemandMob) { var quest = this[nQuestID]; if (!quest.DemandRecords.ContainsKey(mob.MobID)) { return(false); } if (quest.DemandRecords[mob.MobID].nValue != mob.Count) { return(false); } } foreach (var map in pDemand.DemandMap) { var quest = this[nQuestID]; if (!quest.DemandRecords.ContainsKey(map.MapID)) { return(false); } if (quest.DemandRecords[map.MapID].nValue <= 0) { return(false); } } if (pDemand.FieldEnter.Length > 0 && pDemand.FieldEnter.All(map => map == Parent.Stats.dwPosMap)) { return(false); } // TODO taming mob // TODO pet closeness return(true); }
public static void Handle(MapleClient c, PacketReader pr) { try { if (c.NpcEngine != null && c.NpcEngine.IsShop) { byte mode = pr.ReadByte(); int NpcId = c.NpcEngine.NpcId; switch (mode) { case 0: { short shopIndex = pr.ReadShort(); int itemId = pr.ReadInt(); short amount = pr.ReadShort(); c.NpcEngine.BuyItem(itemId, shopIndex, amount); break; } case 1: //sell { short inventoryIndex = pr.ReadShort(); int itemId = pr.ReadInt(); short qty = pr.ReadShort(); MapleInventoryType invType = ItemConstants.GetInventoryType(itemId); switch (invType) { case MapleInventoryType.Equip: case MapleInventoryType.Etc: case MapleInventoryType.Setup: case MapleInventoryType.Use: break; default: return; // Not a valid item } WzItem wzitem = DataBuffer.GetItemById(itemId); if (wzitem == null) { wzitem = DataBuffer.GetEquipById(itemId); } if (wzitem == null) // Item doesnt exist (anymore?) { return; } if (wzitem.NotSale || wzitem.IsCashItem || wzitem.IsQuestItem) { return; } byte response = 0; if (!wzitem.IsQuestItem) { MapleInventory inventory = c.Account.Character.Inventory; MapleItem item = inventory.GetItemSlotFromInventory(invType, inventoryIndex); if (item?.ItemId == itemId && item.Quantity >= qty) { if (inventory.Mesos + wzitem.Price > GameConstants.MAX_MESOS) { response = 2; // You do not have enough mesos } else { inventory.RemoveItemsFromSlot(item.InventoryType, item.Position, qty, true); inventory.GainMesos(wzitem.Price * qty, false, false); } // TODO: buyback } } PacketWriter pw = new PacketWriter(); pw.WriteHeader(SendHeader.NpcTransaction); pw.WriteByte(response); pw.WriteByte(0); pw.WriteByte(0); c.SendPacket(pw); break; } case 3: { c.NpcEngine.Dispose(); break; } default: { c.NpcEngine.ScriptInstance = null; ServerConsole.Warning("Unkown NpcShopActionHandler mode:" + mode); ServerConsole.Info(Functions.ByteArrayToStr(pr.ToArray())); break; } } } } catch (Exception ex) { ServerConsole.Error("NpcShopActionHandler Failure"); ServerConsole.Error(ex.Message); if (c.NpcEngine != null) { c.NpcEngine.Dispose(); } } }
public static CharacterInventoryItems GetInventory(Character pChar, int nItemID) => GetInventory(pChar, ItemConstants.GetInventoryType(nItemID));
/// <summary> /// Handles skill casting. Will return false if skill is unable to cast for any reason, such as not enough resources or invalid skill. /// </summary> /// <param name="nSkillID"></param> /// <param name="bLeft">If the skill is happening to the left of the character</param> /// <param name="bOutsideHandling">When this is true, the function will only process the resource/cooldown portion.</param> /// <returns></returns> public bool Cast(int nSkillID, bool bLeft, bool bOutsideHandling = false, int nSpiritJavelinItemID = 0) { if (Parent.Stats.nHP <= 0) { return(false); // REEEEEEEEE } #if DEBUG Parent.SendMessage("Casting spell " + nSkillID); #endif var skill = Get(nSkillID, true); if (skill == null) { Parent.SendMessage("Unable to find skill."); return(false); } var template = skill.Template; var nSLV = skill.nSLV; if (Parent.Cooldowns.OnCooldown(nSkillID)) { Parent.SendMessage("Trying to cast skill while skill on cooldown."); return(false); } double costMp = skill.MPCost; // done var costMeso = template.MesoR(nSLV); // may not be done.. var itemConsumeId = template.ItemConsume; // done if (Parent.Buffs.Contains((int)Skills.BISHOP_INFINITY)) // party buff { costMp = 0; } else { switch (Parent.Stats.nJob / 10) { case 21: if (Parent.Buffs.Contains((int)Skills.ARCHMAGE1_INFINITY)) { costMp = 0; break; } costMp *= (Parent.Skills.Get((int)Skills.MAGE1_ELEMENT_AMPLIFICATION)?.X_Effect ?? 100.0) * 0.01; goto default; case 22: if (Parent.Buffs.Contains((int)Skills.ARCHMAGE2_INFINITY)) { costMp = 0; break; } costMp *= (Parent.Skills.Get((int)Skills.MAGE2_ELEMENT_AMPLIFICATION)?.X_Effect ?? 100.0) * 0.01; goto default; case 121: // koc mage costMp *= (Parent.Skills.Get((int)Skills.FLAMEWIZARD_ELEMENT_AMPLIFICATION)?.X_Effect ?? 100.0) * 0.01; goto default; case 221: // evan case 222: // evan rounded up (2215-2218) costMp *= (Parent.Skills.Get((int)Skills.EVAN_ELEMENT_AMPLIFICATION)?.X_Effect ?? 100.0) * 0.01; goto default; case 31: if (Parent.Buffs[(int)Skills.BOWMASTER_CONCENTRATION] is BuffSkill pBuff) { costMp *= 1 - (pBuff.Template.X(pBuff.nSLV) * 0.01); } goto default; default: if (Parent.Stats.nMP < Math.Floor(costMp)) { Log.Debug($"Not enough mp to perform skill. Current MP: {Parent.Stats.nMP}. MP required: {costMp}. SkillID: {nSkillID}. CharID: {Parent.dwId}. CharName: {Parent.Stats.sCharacterName}."); return(false); } break; } } // calculate HP cost int costHp; switch ((Skills)nSkillID) { case Skills.DUAL5_FINAL_CUT: case Skills.DRAGONKNIGHT_DRAGON_ROAR: case Skills.DRAGONKNIGHT_SACRIFICE: case Skills.INFIGHTER_MP_RECOVERY: costHp = (int)(Parent.BasicStats.nMHP * template.X(skill.nSLV) * 0.01); break; default: costHp = 0; break; } if (Parent.Stats.nHP <= costHp) { Log.Debug($"Not enough hp to perform skill. Hp required: {costHp}"); return(false); } if (Parent.Stats.nMoney < costMeso) { Log.Debug($"Not enough meso to perform skill. Meso required: {costMeso}"); return(false); } var itemConsumeAmount = template.ItemConsumeAmount; if (nSkillID == (int)Skills.NIGHTLORD_SPIRIT_JAVELIN) { if (!ItemConstants.IsThrowingStar(nSpiritJavelinItemID)) { return(false); } itemConsumeId = nSpiritJavelinItemID; itemConsumeAmount = 200; // we hardcodin' bois } if (itemConsumeId > 0 && itemConsumeAmount > 0) { var valid = false; var itemType = ItemConstants.GetInventoryType(itemConsumeId); foreach (var item in itemType == InventoryType.Etc ? Parent.InventoryEtc : Parent.InventoryConsume) // lol ternary operator in a loop { if (item.Value.nItemID == itemConsumeId && item.Value.nNumber >= itemConsumeAmount) { valid = true; InventoryManipulator.RemoveFrom(Parent, itemType, item.Key, (short)itemConsumeAmount); break; } } if (!valid) { return(false); } } // energy skills switch ((Skills)nSkillID) { case Skills.BUCCANEER_ENERGY_BURSTER: case Skills.STRIKER_ENERGY_BURSTER: case Skills.BUCCANEER_ENERGY_DRAIN: case Skills.STRIKER_ENERGY_DRAIN: case Skills.VIPER_ENERGY_ORB: if (Parent.Combat.nEnergy != SkillLogic.EnergyMax) { Parent.SendMessage($"Insufficient energy. ({Parent.Combat.nEnergy} != {SkillLogic.EnergyMax})."); return(false); } break; } Parent.Modify.Stats(ctx => { if (costHp > 0) { ctx.HP -= costHp; } if (costMp > 0) { ctx.MP -= (int)Math.Floor(costMp); } if (costMeso > 0) { ctx.Money -= costMeso; } }); if (Parent.nPreparedSkill == 0) { var nCdSkillId = nSkillID; var nCdTime = template.Cooltime(skill.nSLV); switch ((Skills)nSkillID) { case Skills.MECHANIC_SAFETY: { if (!Parent.Field.Summons.Any(s => s.dwParentID == dwParentID && (s.nSkillID == (int)Skills.MECHANIC_SATELITE || s.nSkillID == (int)Skills.MECHANIC_SATELITE2 || s.nSkillID == (int)Skills.MECHANIC_SATELITE3))) { return(false); // satellites must be active to cast this skill } } break; case Skills.WILDHUNTER_SWALLOW: case Skills.MECHANIC_TESLA_COIL: nCdTime = 0; break; case Skills.WILDHUNTER_SWALLOW_DUMMY_ATTACK: case Skills.WILDHUNTER_SWALLOW_DUMMY_BUFF: var pTempTemplate = Parent.Skills.Get((int)Skills.WILDHUNTER_SWALLOW); nCdSkillId = pTempTemplate.nSkillID; nCdTime = (short)pTempTemplate.CoolTimeSeconds; break; } if (nCdTime > 0) { Parent.Cooldowns.UpdateOrInsert(nCdSkillId, (short)nCdTime); } } if (template.is_heros_will_skill) { Parent.Buffs.CancelAllDebuffs(); return(true); } if (bOutsideHandling || template.IsNotBuff) { return(true); } if (SkillLogic.is_teleport_mastery_skill(nSkillID)) { HandleTeleportMastery(nSkillID, nSLV); return(true); } switch ((Skills)nSkillID) { case Skills.HERO_ENRAGE: { Parent.Buffs.Remove((int)Skills.CRUSADER_COMBO_ATTACK); Parent.Combat.ComboCounter = 0; } break; case Skills.CRUSADER_MAGIC_CRASH: case Skills.DRAGONKNIGHT_MAGIC_CRASH: case Skills.KNIGHT_MAGIC_CRASH: CastAOEMobStat(nSkillID); return(true); case Skills.NIGHTLORD_SPIRIT_JAVELIN: { Parent.Buffs.Remove(nSkillID); var buff = new BuffSkill(nSkillID, nSLV); buff.GenerateSpiritJavelin(nSpiritJavelinItemID); Parent.Buffs.Add(buff); } return(true); case Skills.BMAGE_SUPER_BODY: DoSuperBody(nSLV); return(true); case Skills.BMAGE_AURA_BLUE: DoAuraSkill(SecondaryStatFlag.BlueAura, (int)Skills.BMAGE_AURA_BLUE_ADVANCED, nSkillID, nSLV); return(true); case Skills.BMAGE_AURA_YELLOW: DoAuraSkill(SecondaryStatFlag.YellowAura, (int)Skills.BMAGE_AURA_YELLOW_ADVANCED, nSkillID, nSLV); return(true); case Skills.BMAGE_AURA_DARK: DoAuraSkill(SecondaryStatFlag.DarkAura, (int)Skills.BMAGE_AURA_DARK_ADVANCED, nSkillID, nSLV); return(true); case Skills.SHADOWER_SMOKE_SHELL: case Skills.EVAN_RECOVERY_AURA: case Skills.MAGE1_POISON_MIST: case Skills.FLAMEWIZARD_FLAME_GEAR: case Skills.BMAGE_SHELTER: CastAffectedAreaSkill (nSkillID, skill.nSLV, (short)skill.BuffTime, Parent.Position.CurrentXY, template.LT, template.RB); return(true); case Skills.THIEFMASTER_CHAKRA: if (Parent.Stats.nHP < Parent.BasicStats.nMHP * 0.5) { // BMS // dwFlaga = sd->nY + 100; // tCur = CRand32::Random(&g_rand) % 100 + 100; // CQWUser::IncHP(v5, ((tCur * v5->m_basicStat.nLUK * 0.033 + v5->m_basicStat.nDEX) * dwFlaga * 0.002), 0); var nMultiplier = skill.Y_Effect + 100; var nRand = Constants.Rand.Next() % 100 + 100; Parent.Modify.Heal((int)((nRand * Parent.BasicStats.nLUK * 0.033 + Parent.BasicStats.nDEX) * nMultiplier * 0.002)); return(true); } return(false); case Skills.KNIGHT_RESTORATION: Parent.Modify.Heal((int)(Parent.BasicStats.nMHP * skill.X_Effect)); return(true); case Skills.FLAMEWIZARD_SLOW: case Skills.WIZARD1_SLOW: case Skills.WIZARD2_SLOW: case Skills.NIGHTLORD_NINJA_AMBUSH: case Skills.SHADOWER_NINJA_AMBUSH: case Skills.HERMIT_SHADOW_WEB: case Skills.NIGHTWALKER_SHADOW_WEB: case Skills.DUAL3_FLASH_BANG: case Skills.DUAL4_UPPER_STAB: case Skills.HUNTER_ARROW_BOMB: case Skills.BOWMASTER_VENGEANCE: case Skills.PAGE_THREATEN: CastAOEMobStat(nSkillID); return(true); case Skills.DUAL4_OWL_DEATH: if (skill.DoProp()) { Parent.Buffs.AddSkillBuff(nSkillID, nSLV, Parent.Buffs.BuffTimeModifier()); Parent.Combat.OwlSpiritCount = 10; } return(true); case Skills.ADMIN_HOLY_SYMBOL: foreach (var pChar in Parent.Field.Users) { pChar.Buffs.AddSkillBuff(nSkillID, nSLV, Parent.Buffs.BuffTimeModifier()); } return(true); case Skills.WILDHUNTER_SWALLOW: SwallowMob(Parent.m_dwSwallowMobID, nSLV); return(true); case Skills.VALKYRIE_DICE: case Skills.MECHANIC_DICE: case Skills.BUCCANEER_DICE: DoDice(nSkillID, nSLV); return(true); case Skills.INFIGHTER_MP_RECOVERY: Parent.Modify.Heal(0, (int)(Parent.BasicStats.nMHP * (0.5 + (0.1 * nSLV)))); // hard coding ftw return(true); case Skills.CLERIC_HEAL: DoPartyHeal(nSkillID, template.HP(nSLV)); return(true); case Skills.BISHOP_RESURRECTION: if (Parent.Party?.Count > 1) { Parent.Party.ApplyBuffToParty(Parent, Parent.Field.dwUniqueId, nSkillID, nSLV); } return(true); case Skills.PRIEST_DISPEL: if (Parent.Party?.Count > 1) { Parent.Party.ApplyBuffToParty(Parent, Parent.Field.dwUniqueId, nSkillID, nSLV); } else { Parent.Buffs.CancelAllDebuffs(); } CastAOEMobStat(nSkillID); // lazy impl return(true); case Skills.KNIGHT_COMBAT_ORDERS: DoCombatOrders(nSkillID, nSLV); return(true); case Skills.BISHOP_INFINITY: // only a party buff for clerics (custom) if (Parent.Party?.Count > 1) { Parent.Party.ApplyBuffToParty(Parent, Parent.Field.dwUniqueId, nSkillID, nSLV, 2); return(true); } break; case Skills.VIPER_TIME_LEAP: DoTimeleap(nSkillID); return(true); case Skills.MECHANIC_HN07: { if (Parent.Skills.Get((int)Skills.MECHANIC_HN07_UPGRADE, false) is SkillEntry se) { Parent.Buffs.AddSkillBuff(se.nSkillID, se.nSLV); return(true); } } break; } if (template.Time(nSLV) != 0) { var buffTimeModifier = Parent.Buffs.BuffTimeModifier(); if (Parent.Party?.Count > 1 && template.IsPartyBuff) { Parent.Party.ApplyBuffToParty (Parent, Parent.Field.dwUniqueId, nSkillID, nSLV, buffTimeModifier); } else { Parent.Buffs.AddSkillBuff(nSkillID, nSLV, buffTimeModifier); } } return(true); }
public static void Handle_UserSkillLearnItemUseRequest(WvsGameClient c, CInPacket p) { int dwTickCount = p.Decode4(); short nPOS = p.Decode2(); int nItemID = p.Decode4(); c.Character.Action.Enable(); if (c.Character.Stats.nHP <= 0) { return; } if (InventoryManipulator.GetItem(c.Character, ItemConstants.GetInventoryType(nItemID), nPOS) is GW_ItemSlotBundle item && item.Template is ConsumeItemTemplate template) { var jobroot = Math.Floor(c.Character.Stats.nJob * 0.01); // 3500 -> 35 var bUsed = false; var bSuccess = false; var bIsMasterBook = item.nItemID / 10000 == 229; foreach (var skillId in template.SkillData) { var skillJob = (int)Math.Floor(skillId / 10000f); // 35111010 -> 3511 var skillRoot = (int)Math.Floor(skillJob / 100f); // 3511 -> 35 if (skillRoot == jobroot) // this can only be true once { if (skillJob > c.Character.Stats.nJob) { break; } var skill = c.Character.Skills.FirstOrDefault(s => s.nSkillID == skillId); if (bIsMasterBook) { if (skill is null || skill.nSLV < template.ReqSkillLevel || skill.CurMastery >= template.MasterLevel) { return; } } else { if (skill != null && skill.CurMastery > 0) { break; } } bUsed = true; if (template.SuccessRate != 100) { if (Constants.Rand.Next() % 100 > template.SuccessRate) { break; } } c.Character.Modify.Skills(mod => mod.AddEntry(skillId, s => s.CurMastery = (byte)template.MasterLevel)); bSuccess = true; break; } } if (bUsed) { InventoryManipulator.RemoveFrom(c.Character, item.InvType, nPOS); // always remove } c.Character.Field.Broadcast(CPacket.SkillLearnItemResult(c.dwCharId, bIsMasterBook, bUsed, bSuccess)); } }
private static void BuyItem(Character pChar, short nPos, int nItemId, short nCount) { var cShop = pChar.Socket.ActiveShop; // price is 0 for invis items if (!cShop.ContainsItem(nItemId) || cShop.GetItemPrice(nItemId) <= 0 || cShop.GetItemLevelLimited(nItemId) > pChar.Stats.nLevel) { pChar.SendMessage("Trying to buy an item that doesn't exist in the shop."); pChar.SendPacket(CPacket.CShopDlg.ShopResult(ShopRes.BuyUnknown)); return; } nCount = ItemConstants.is_treat_singly(nItemId) ? (short)1 : nCount; var nPricePerCount = cShop.GetItemPrice(nItemId); var nFinalPrice = nPricePerCount * nCount; if (nFinalPrice > pChar.Stats.nMoney) { pChar.SendMessage("Trying to buy an item without enough money."); pChar.SendPacket(CPacket.CShopDlg.ShopResult(ShopRes.BuyNoMoney)); return; } var nInvType = ItemConstants.GetInventoryType(nItemId); if (InventoryManipulator.CountFreeSlots(pChar, nInvType) < 1) { pChar.SendMessage("Please make some space in your inventory."); pChar.SendPacket(CPacket.CShopDlg.ShopResult(ShopRes.BuyUnknown)); return; } var pItem = MasterManager.CreateItem(nItemId, false); var slotmax = pItem.SlotMax; if (pChar.Skills.Get(false, (int)Skills.NIGHTWALKER_JAVELIN_MASTERY, (int)Skills.ASSASSIN_JAVELIN_MASTERY) is SkillEntry se) { slotmax += (short)se.Y_Effect; } if (slotmax < nCount * cShop.GetItemQuantity(nItemId)) { pChar.SendMessage("Unable to purchase more than one slot of items at a time."); pChar.SendPacket(CPacket.CShopDlg.ShopResult(ShopRes.BuyUnknown)); return; } pChar.SendPacket(CPacket.CShopDlg.ShopResult(ShopRes.BuySuccess)); pItem.nNumber = (short)(pItem.IsRechargeable ? slotmax : nCount * cShop.GetItemQuantity(nItemId)); pChar.SendMessage("final price: " + nFinalPrice); InventoryManipulator.InsertInto(pChar, pItem); pChar.Modify.GainMeso(-nFinalPrice, false); }
public static void Handle(MapleClient c, PacketReader pr) { MapleCharacter chr = c.Account.Character; if (!chr.DisableActions()) { return; } int tickCount = pr.ReadInt(); short slot = pr.ReadShort(); int itemId = pr.ReadInt(); MapleItem item = chr.Inventory.GetItemSlotFromInventory(ItemConstants.GetInventoryType(itemId), slot); bool removeItem = true; if (item == null || item.ItemId != itemId) { return; } switch (itemId) { case 5062006: //Platinum Miracle Cube { int equipSlot = pr.ReadInt(); if (equipSlot < 0) { return; } MapleEquip equip = chr.Inventory.GetItemSlotFromInventory(MapleInventoryType.Equip, (short)equipSlot) as MapleEquip; if (equip == null) { return; } if (!MapleEquipEnhancer.CubeItem(equip, CubeType.PlatinumMiracle, chr)) { removeItem = false; } break; } case 5072000: //Super Megaphone case 5072001: //Super Megaphone { if (!CanMegaPhone(c.Account.Character)) { chr.EnableActions(); break; } string message = pr.ReadMapleString(); if (message.Length > 60) { return; } bool whisperIcon = pr.ReadBool(); message = string.Format("{0} : {1}", c.Account.Character.Name, message); Program.BroadCastWorldPacket(MapleCharacter.ServerNotice(message, 3, c.Channel, whisperIcon)); break; } case 5570000: //Vicious hammer { removeItem = false; //Handled in UseGoldenHammerHandler pr.Skip(4); short equipSlot = (short)pr.ReadInt(); MapleEquip equip = chr.Inventory.GetItemSlotFromInventory(MapleInventoryType.Equip, equipSlot) as MapleEquip; if (equip != null) { UseGoldenHammerHandler.DoHammer(item, equip, chr); } break; } default: { ServerConsole.Warning("Unhandled UseSpecialItem: {0}", itemId); removeItem = false; chr.SendPopUpMessage("You cannot use this item"); chr.EnableActions(); break; } } if (removeItem) { chr.Inventory.RemoveItemsFromSlot(item.InventoryType, item.Position, 1); } chr.EnableActions(false); }