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 QuestResultType TryExchange(int nIncMoney, QuestAct.ActItem[] aActItem) { if (nIncMoney == 0 && aActItem.Length <= 0) { return(QuestResultType.Success); } if (nIncMoney < 0 && Parent.Stats.nMoney < nIncMoney) { return(QuestResultType.Failed_Meso); } foreach (var item in aActItem) { if (item.Item.Count > 0) { if (!InventoryManipulator.HasSpace(Parent, item.Item.ItemID, (short)item.Item.Count)) { return(QuestResultType.Failed_Inventory); // -> Etc inventory is full } } else { if (!InventoryManipulator.ContainsItem(Parent, item.Item.ItemID, (short)item.Item.Count)) { return(QuestResultType.Failed_Unknown); // idk what code to give them } } } Parent.Modify.GainMeso(nIncMoney); var weight = 0; foreach (var item in aActItem) { if (item.ProbRate != 0) { weight += item.ProbRate; } } var itemGiven = false; foreach (var item in aActItem.Shuffle()) { if (item.Item.Count < 0) { InventoryManipulator.RemoveQuantity(Parent, item.Item.ItemID, (short)item.Item.Count); } else { if (item.ProbRate == 0) { var newItem = MasterManager.CreateItem(item.Item.ItemID, false); if (!newItem.IsEquip) { newItem.nNumber = (short)item.Item.Count; } InventoryManipulator.InsertInto(Parent, newItem); } else if (!itemGiven) { var rand = Constants.Rand.Next(0, weight); if (rand < item.ProbRate) { var newItem = MasterManager.CreateItem(item.Item.ItemID, false); if (!newItem.IsEquip) { newItem.nNumber = (short)item.Item.Count; } InventoryManipulator.InsertInto(Parent, newItem); itemGiven = true; } else { weight -= item.ProbRate; } } } } return(QuestResultType.Success); }
public bool HasItem(int itemId, short amount = 1) => InventoryManipulator.ContainsItem(Character, itemId, 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); }
private static void HandleCreateItemOp(Character pChar, int nItemID, bool bStimulantUsed, List <int> aGems) { // BEGIN VERIFICATION //var pMakerItem = MasterManager.EtcTemplates.MakerData(nItemID); var makerItem = MasterManager.ItemMakeTemplates[nItemID]; // verify maker item exists if (makerItem is null) { pChar.SendMessage("Null item maker template."); return; } // verify player is high enough level to use recipe if (makerItem.ReqLevel > pChar.Stats.nLevel + 6) { pChar.SendMessage("Verify the item level you're trying to craft is no more than 6 above your own."); return; } // verify player has enough meso if (makerItem.Meso > pChar.Stats.nMoney) { pChar.SendMessage("Verify you have the correct amount of mesos."); return; } var pCharMakerSkill = pChar.Skills.Get(Common.GameLogic.SkillLogic.get_novice_skill_as_race(Common.GameLogic.SkillLogic.NoviceSkillID.MakerSkill, pChar.Stats.nJob)); // verify player maker skill level is high enough if (makerItem.ReqSkillLevel > (pCharMakerSkill?.nSLV ?? 0)) { pChar.SendMessage($"Verify maker skill level. {makerItem.ReqSkillLevel} < {(pCharMakerSkill?.nSLV ?? 0)}"); return; } var(nStimulantItemSlot, pStimulantItem) = InventoryManipulator.GetAnyItem(pChar, InventoryType.Etc, makerItem.CatalystID); // verify stimulant (catalyst) exists in player inventory if (bStimulantUsed && pStimulantItem is null) { pChar.SendMessage("Verify you possess the correct stimulant item."); return; } // verify equip slot availability if (InventoryManipulator.CountFreeSlots(pChar, InventoryType.Equip) < 1) { pChar.SendMessage("Please make more room in your equip inventory."); return; } if (InventoryManipulator.CountFreeSlots(pChar, InventoryType.Etc) < makerItem.RandomReward.Length) { pChar.SendMessage("Please make more room in your etc inventory."); return; } // verify required items exist in player inventory if (makerItem.Recipe.Any(item => !InventoryManipulator.ContainsItem(pChar, item.ItemID, (short)item.Count))) { pChar.SendMessage("Verify you possess all the required components."); return; } var aGemItemIds = new List <int>(); var aGemItemTypes = new List <int>(); // remove duplicate items/types and get item slots for gems foreach (var entry in aGems) { var(nGemSlot, pGemItem) = InventoryManipulator.GetAnyItem(pChar, InventoryType.Etc, entry); if (pGemItem is null || nGemSlot == 0 || !(pGemItem.Template is GemEffectTemplate)) { continue; } // idk how it would be 0 but we check anyway if (!aGemItemTypes.Contains(entry / 100) && !aGemItemIds.Contains(pGemItem.nItemID) && pGemItem.nNumber > 0) { aGemItemIds.Add(pGemItem.nItemID); aGemItemTypes.Add(entry / 100); } } // END VERIFICATION // BEGIN RECIPE PROCESSING // remove meso cost from inventory if (makerItem.Meso > 0) { pChar.Modify.GainMeso(-makerItem.Meso); } // remove stimulant from inventory if (bStimulantUsed) { InventoryManipulator.RemoveQuantity(pChar, pStimulantItem.nItemID, 1); } // remove recipe items from inventory foreach (var item in makerItem.Recipe) { InventoryManipulator.RemoveQuantity(pChar, item.ItemID, (short)item.Count); } var bSuccess = true; if (bStimulantUsed && Constants.Rand.Next(100) >= 90) { bSuccess = false; } else { // BEGIN MAKER ITEM CREATION var pNewItemRaw = MasterManager.CreateItem(makerItem.TemplateId); if (pNewItemRaw is GW_ItemSlotEquip pNewItemEquip) { pNewItemEquip.RemainingUpgradeCount = (byte)makerItem.TUC; // remove gems from inventory foreach (var nGemItemId in aGemItemIds) { var pGemItemRaw = InventoryManipulator.GetAnyItem(pChar, InventoryType.Etc, nGemItemId).Item2; if (pGemItemRaw.Template is GemEffectTemplate pGemItem) { // gems only have one modifier each if (pGemItem.incPAD > 0) { pNewItemEquip.niPAD += (short)(pGemItem.incPAD * (bStimulantUsed ? 2 : 1)); } else if (pGemItem.incPDD > 0) { pNewItemEquip.niPDD += (short)(pGemItem.incPDD * (bStimulantUsed ? 2 : 1)); } else if (pGemItem.incMAD > 0) { pNewItemEquip.niMAD += (short)(pGemItem.incMAD * (bStimulantUsed ? 2 : 1)); } else if (pGemItem.incMDD > 0) { pNewItemEquip.niMDD += (short)(pGemItem.incMDD * (bStimulantUsed ? 2 : 1)); } else if (pGemItem.incSTR > 0) { pNewItemEquip.niSTR += (short)(pGemItem.incSTR * (bStimulantUsed ? 2 : 1)); } else if (pGemItem.incINT > 0) { pNewItemEquip.niINT += (short)(pGemItem.incINT * (bStimulantUsed ? 2 : 1)); } else if (pGemItem.incDEX > 0) { pNewItemEquip.niDEX += (short)(pGemItem.incDEX * (bStimulantUsed ? 2 : 1)); } else if (pGemItem.incLUK > 0) { pNewItemEquip.niLUK += (short)(pGemItem.incLUK * (bStimulantUsed ? 2 : 1)); } else if (pGemItem.incACC > 0) { pNewItemEquip.niACC += (short)(pGemItem.incACC * (bStimulantUsed ? 2 : 1)); } else if (pGemItem.incEVA > 0) { pNewItemEquip.niEVA += (short)(pGemItem.incEVA * (bStimulantUsed ? 2 : 1)); } else if (pGemItem.incMaxHP > 0) { pNewItemEquip.niMaxHP += (short)(pGemItem.incMaxHP * (bStimulantUsed ? 2 : 1)); } else if (pGemItem.incMaxMP > 0) { pNewItemEquip.niMaxMP += (short)(pGemItem.incMaxMP * (bStimulantUsed ? 2 : 1)); } else if (pGemItem.incJump > 0) { pNewItemEquip.niJump += (short)(pGemItem.incJump * (bStimulantUsed ? 2 : 1)); } else if (pGemItem.incSpeed > 0) { pNewItemEquip.niSpeed += (short)(pGemItem.incSpeed * (bStimulantUsed ? 2 : 1)); } else if (pGemItem.incReqLevel < 0) { pNewItemEquip.nLevel = (byte)(pNewItemEquip.nLevel + (pGemItem.incReqLevel * (bStimulantUsed ? 2 : 1))); } else if (pGemItem.RandOption > 0) { var gX = new GaussianRandom(); var nRange = pGemItem.RandOption * (bStimulantUsed ? 2 : 1); if (pNewItemEquip.niMaxHP > 0) { pNewItemEquip.niMaxHP = (short)Math.Max(0, gX.GaussianDistributionVariation(pNewItemEquip.niMaxHP, nRange, false)); } if (pNewItemEquip.niMaxMP > 0) { pNewItemEquip.niMaxMP = (short)Math.Max(0, gX.GaussianDistributionVariation(pNewItemEquip.niMaxMP, nRange, false)); } if (pNewItemEquip.niPAD > 0) { pNewItemEquip.niPAD = (short)Math.Max(0, gX.GaussianDistributionVariation(pNewItemEquip.niPAD, nRange, false)); } if (pNewItemEquip.niMAD > 0) { pNewItemEquip.niMAD = (short)Math.Max(0, gX.GaussianDistributionVariation(pNewItemEquip.niMAD, nRange, false)); } if (pNewItemEquip.niPDD > 0) { pNewItemEquip.niPDD = (short)Math.Max(0, gX.GaussianDistributionVariation(pNewItemEquip.niPDD, nRange, false)); } if (pNewItemEquip.niMDD > 0) { pNewItemEquip.niMDD = (short)Math.Max(0, gX.GaussianDistributionVariation(pNewItemEquip.niMDD, nRange, false)); } if (pNewItemEquip.niSpeed > 0) { pNewItemEquip.niSpeed = (short)Math.Max(0, gX.GaussianDistributionVariation(pNewItemEquip.niSpeed, nRange, false)); } if (pNewItemEquip.niJump > 0) { pNewItemEquip.niJump = (short)Math.Max(0, gX.GaussianDistributionVariation(pNewItemEquip.niJump, nRange, false)); } } // pNewItemEquip.ApplyRandStatOption(pGemItem.RandOption * (bStimulantUsed ? 2 : 1), false); else if (pGemItem.RandStat > 0) { var gX = new GaussianRandom(); var nRange = pGemItem.RandStat * (bStimulantUsed ? 2 : 1); if (pNewItemEquip.niSTR > 0) { pNewItemEquip.niSTR = (short)Math.Max(0, gX.GaussianDistributionVariation(pNewItemEquip.niSTR, nRange, false)); } if (pNewItemEquip.niLUK > 0) { pNewItemEquip.niLUK = (short)Math.Max(0, gX.GaussianDistributionVariation(pNewItemEquip.niLUK, nRange, false)); } if (pNewItemEquip.niINT > 0) { pNewItemEquip.niINT = (short)Math.Max(0, gX.GaussianDistributionVariation(pNewItemEquip.niINT, nRange, false)); } if (pNewItemEquip.niDEX > 0) { pNewItemEquip.niDEX = (short)Math.Max(0, gX.GaussianDistributionVariation(pNewItemEquip.niDEX, nRange, false)); } if (pNewItemEquip.niACC > 0) { pNewItemEquip.niACC = (short)Math.Max(0, gX.GaussianDistributionVariation(pNewItemEquip.niACC, nRange, false)); } if (pNewItemEquip.niEVA > 0) { pNewItemEquip.niEVA = (short)Math.Max(0, gX.GaussianDistributionVariation(pNewItemEquip.niEVA, nRange, false)); } } } } InventoryManipulator.InsertInto(pChar, pNewItemEquip); } else { pNewItemRaw.nNumber = (short)makerItem.ItemNum; InventoryManipulator.InsertInto(pChar, pNewItemRaw); } // remove gems if any foreach (var nGemItemId in aGemItemIds) { InventoryManipulator.RemoveQuantity(pChar, nGemItemId, 1); //InventoryManipulator.RemoveFrom(pChar, (byte)InventoryType.Etc, itemSlot, 1); } foreach (var entry in makerItem.RandomReward) { if (Constants.Rand.Next(100) >= entry.Prob) { continue; } var pRandRewardItem = MasterManager.CreateItem(entry.ItemID); pRandRewardItem.nNumber = (short)entry.ItemNum; InventoryManipulator.InsertInto(pChar, pRandRewardItem); } // END MAKER ITEM CREATION } // END RECIPE PROCESSING // SEND RESPONSE PACKETS pChar.SendPacket(CreateItemResponse(bSuccess, bStimulantUsed, makerItem, aGemItemIds)); pChar.SendPacket(MakerItemEffectLocal(bSuccess)); pChar.Field.Broadcast(MakerItemEffectRemote(pChar.dwId, bSuccess)); }