/// <summary> /// Handles HP/MP/EXP reduction on death. /// Cancels all buffs. /// Warps player to return map. /// </summary> /// <param name="user"></param> public virtual void OnUserWarpDie(Character user, bool bLoseExp = true) { user.StatisticsTracker.nDeaths += 1; if (nFieldDeathCount > 0) { UpdateDeathCount(--nFieldDeathCount); } if (Template.HasNoExpDecrease() || !bLoseExp) { user.Modify.Stats(ctx => { ctx.HP = user.BasicStats.nMHP; ctx.MP = user.BasicStats.nMMP; }); } else { const int nCharmId = 5130000; if (InventoryManipulator.RemoveQuantity(user, nCharmId, 1)) { // TODO use real notification packet for this user.SendMessage($"A safety charm has been used to avoid losing exp!"); user.Modify.Heal((int)(user.BasicStats.nMHP * 0.33), (int)(user.BasicStats.nMMP * 0.33)); } else { user.Modify.Stats(ctx => { ctx.decrease_exp(user.Field.Template.Town || user.Field.Mobs.aMobGen.Count == 0); ctx.HP = 1; ctx.MP = 1; }); } } user.Buffs.CancelAllBuffs(); user.Action.SetField(user.Field.ReturnMapId); }
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 RemoveItem(int itemId, short amount = 1) => InventoryManipulator.RemoveQuantity(Character, itemId, amount);
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)); }