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."); } }
public bool ActivateSinglePet(short nPos, bool bForce = false) { if (Pets[0] != null && !bForce) { DeactivateSinglePet(); return(true); } if (Parent.Field.Template.HasNoPetLimit()) { Parent.SendMessage("Pets are not allowed in this map"); return(false); } var pItemRaw = InventoryManipulator.GetItem(Parent, InventoryType.Cash, nPos); if (pItemRaw is GW_ItemSlotPet pet) { if (pet.PetTemplate.EvolNo > 0) { Parent.SendMessage("Evolving have not been coded yet, sorry :("); return(false); } ActivatePet(pet, nPos, 0); return(true); } return(false); }
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); }
private static void RechargeItem(Character pChar, short nSlot) { var pItem = InventoryManipulator.GetItem(pChar, InventoryType.Consume, nSlot); if (pItem is null) { pChar.SendMessage("Trying to recharge null item."); pChar.SendPacket(CPacket.CShopDlg.ShopResult(ShopRes.RechargeIncorrectRequest)); return; } if (!ItemConstants.IsRechargeableItem(pItem.nItemID)) { pChar.SendMessage("Trying to recharge item that isn't rechargeable."); pChar.SendPacket(CPacket.CShopDlg.ShopResult(ShopRes.RechargeIncorrectRequest)); return; } 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 (pItem.nNumber >= slotmax) { pChar.SendMessage("Trying to recharge item that is fully charged."); pChar.SendPacket(CPacket.CShopDlg.ShopResult(ShopRes.RechargeIncorrectRequest)); return; } var dUnitPrice = (pItem.Template as ConsumeItemTemplate).UnitPrice; var nRechargeNeeded = slotmax - pItem.nNumber; var nTotalRechargePrice = (int)Math.Floor(nRechargeNeeded * dUnitPrice); if (pChar.Stats.nMoney < nTotalRechargePrice) { pChar.SendPacket(CPacket.CShopDlg.ShopResult(ShopRes.RechargeNoMoney)); return; } pChar.Modify.GainMeso(-nTotalRechargePrice); pItem.nNumber = slotmax; pChar.Modify.Inventory(ctx => { ctx.UpdateQuantity(InventoryType.Consume, nSlot, pItem.nNumber); }); pChar.SendPacket(CPacket.CShopDlg.ShopResult(ShopRes.RechargeSuccess)); }
private static void HandleDisassembleOp(Character pChar, InventoryType nInvType, int nItemID, int nSlotPos) { var pItem = InventoryManipulator.GetItem(pChar, nInvType, (short)nSlotPos); if (pItem is GW_ItemSlotEquip pItemEquip) { var nCost = pItemEquip.Template.Price * 0.1363; } else { } }
public void EncodeEquippedRings(COutPacket p) { #region COUPLE_RING p.Encode1(0); // TODO #endregion #region FRIENDSHIP_RING GW_FriendRecord pFriendshipRing = null; var nFriendshipRingID = 0; long nFriendShipSN = 0; for (var bp = BodyPart.BP_RING1; bp < BodyPart.BP_RING4; bp++) { var item = InventoryManipulator.GetItem(Parent, bp, true); if (item is null) { continue; } if (ItemConstants.is_friendship_equip_item(item.nItemID)) { pFriendshipRing = lFriendRecord.FirstOrDefault(ring => ring.liSN == item.liSN); break; } } p.Encode1(pFriendshipRing != null); if (pFriendshipRing != null) { p.Encode8(pFriendshipRing.liSN); p.Encode8(pFriendshipRing.liPairSN); p.Encode4(pFriendshipRing.dwFriendItemID); } #endregion #region MARRIAGE_RING p.Encode1(0); // TODO #endregion }
public void HandleAddItem(CInPacket p, Character pChar) { if (dwFirstLockerId == pChar.dwId || !acceptedInvite) { return; } var nTI = (InventoryType)p.Decode1(); var nCurInvSlot = p.Decode2(); // in inventory var nCount = p.Decode2(); var nTargetSlot = p.Decode1(); // in trade window var pItem = InventoryManipulator.GetItem(pChar, nTI, nCurInvSlot); var tempInv = GetTempInv(pChar); if (pItem is null || !tempInv.CanAddToSlot(nTargetSlot)) { return; } if (ItemConstants.is_treat_singly(pItem.nItemID)) { nCount = -1; // negative amount clears the slot } else { nCount = Math.Min(pItem.nNumber, Math.Abs(nCount)); } InventoryManipulator.RemoveFrom(pChar, nTI, nCurInvSlot, nCount); if (pItem is GW_ItemSlotBundle pBundle && !pBundle.IsRechargeable) { pItem = pItem.DeepCopy(); pItem.nNumber = nCount; } var pTempItem = new TempItem(pItem, nCurInvSlot, nTargetSlot); tempInv.Add(pTempItem); Parent.SendPacket(AddItemPacket(pTempItem, !IsOwner(pChar))); Partner.SendPacket(AddItemPacket(pTempItem, IsOwner(pChar))); }
// use this when we implement mulit-pet public bool ActivatePet(short nPos, bool bLeader) { throw new InvalidOperationException("Multipet not active"); var pItemRaw = InventoryManipulator.GetItem(Parent, InventoryType.Cash, nPos); if (pItemRaw is GW_ItemSlotPet cPetItem) { if (cPetItem.PetTemplate.EvolNo > 0) { Parent.SendMessage("Evolving pets are not currently handled. Please try again later."); return(false); } if (DeactivatePet(cPetItem.liCashItemSN)) { return(true); } byte nIdx = 0xFF; for (byte i = 0; i < 3; i++) { if (Pets[i] == null) { nIdx = i; break; } } if (nIdx == 0xFF) { return(false); } ActivatePet(cPetItem, nPos, nIdx); Parent.Modify.UpdatePetLocker(); return(true); } return(false); }
public void EncodeMultiPetInfo(COutPacket p) // this is just used for the CharacterInfo packet { for (byte i = 0; i < 3; i++) { if (Pets[i] != null) { p.Encode1(1); var cp = Pets[i]; p.Encode4(cp.dwTemplateID); p.EncodeString(cp.sName); p.Encode1(cp.Level); p.Encode2(cp.Tameness); p.Encode1(cp.Repleteness); //i think p.Encode2(cp.Skill); p.Encode4(InventoryManipulator.GetItem(Parent, petwearparts[i], true)?.nItemID ?? 0); // TODO verify } } p.Encode1(0); }
/// <summary> /// Teleport scroll handling. /// </summary> /// <param name="nPOS"></param> /// <param name="nItemID"></param> public void UsePortalScroll(int nItemID, short nPOS) { if (Parent.Stats.nHP <= 0) { return; } if (Parent.Field.Template.HasPortalScrollLimit()) { return; } if (InventoryManipulator.GetItem(Parent, InventoryType.Consume, nPOS)?.Template is ConsumeItemTemplate template) { if (template.MoveTo > 0) { Parent.Action.SetField(template.MoveTo == 999999999 ? Parent.Field.ReturnMapId : template.MoveTo); } } InventoryManipulator.RemoveFrom(Parent, InventoryType.Consume, nPOS); }
public void AddItem(CInPacket p) { var nTI = (InventoryType)p.Decode1(); var nPOS = p.Decode2(); var nBundles = Math.Max((short)1, p.Decode2()); var nPricePerBundle = Math.Max((short)1, p.Decode2()); var nPrice = Math.Max(1, p.Decode4()); var pItem = InventoryManipulator.GetItem(Parent, nTI, nPOS); if (pItem is null) { Parent.SendMessage("item is null u fucc"); return; } var nQuantityRequested = -1; // negative so its removed completely from inventory if (!ItemConstants.is_treat_singly(pItem.nItemID)) { nQuantityRequested = nBundles * nPricePerBundle; if (pItem.nNumber < nQuantityRequested) { return; // f*****g retard } } InventoryManipulator.RemoveFrom(Parent, nTI, nPOS, (short)nQuantityRequested); Inventory.Add(new TempItem(pItem, nPrice, nPricePerBundle, nBundles)); Refresh(Parent); Parent.SendMessage($"Bundles: {nBundles}, PricePerBundle: {nPricePerBundle}, Price: {nPrice}"); // TODO packet editing checks }
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 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)); } }
/** * Consumeable item buffs will be routed here. * This includes HP/MP items along with temp stat increase items */ public void UsePotion(int nItemID, short nPOS) { if (Parent.Stats.nHP <= 0) { return; } if (InventoryManipulator.GetItem(Parent, InventoryType.Consume, nPOS)?.Template is ConsumeItemTemplate template) { if (Parent.Field is CField_Battlefield bf) // if not remove item anyway cuz they shouldnt have it { // TODO effects => Effect/BasicEff/ItemSkill/Success if (template.BFSkill < 0) { if (BattlefieldData.SheepConsumable(nItemID) || BattlefieldData.WolfConsumable(nItemID)) { var newBuff = new BuffConsume(nItemID); newBuff.GenerateConsumeable(Parent); } } else { switch (template.BFSkill) // we hardcodin' bois { case 0: Parent.SendMessage("You cry at the Wolf, and it slows down as if it's in shock."); bf.Users.ForEach(u => { if (bf.GetPlayerTeam(u.dwId) == BattlefieldData.BattlefieldTeams.Wolves) { u.Buffs.OnStatChangeByMobSkill(MasterManager.MobSkillTemplates[126][9], 0, 0); } }); break; case 1: Parent.SendMessage("You attack the Wolf. He should be momentarily stunned."); bf.Users.ForEach(u => { if (bf.GetPlayerTeam(u.dwId) == BattlefieldData.BattlefieldTeams.Wolves) { u.Buffs.OnStatChangeByMobSkill(MasterManager.MobSkillTemplates[123][14], 0, 0); } }); break; case 2: Parent.Field.BroadcastNotice("The Sheep are in a state of confusion."); bf.Users.ForEach(u => { if (bf.GetPlayerTeam(u.dwId) != BattlefieldData.BattlefieldTeams.Wolves) { u.Buffs.OnStatChangeByMobSkill(MasterManager.MobSkillTemplates[132][4], 0, 0); } }); break; case 3: Parent.Field.BroadcastNotice("The Wolves have slowed down."); bf.Users.ForEach(u => { if (bf.GetPlayerTeam(u.dwId) == BattlefieldData.BattlefieldTeams.Wolves) { u.Buffs.OnStatChangeByMobSkill(MasterManager.MobSkillTemplates[126][10], 0, 0); } }); break; case 4: Parent.Field.BroadcastNotice("The Sheep are momentarily stunned."); bf.Users.ForEach(u => { if (bf.GetPlayerTeam(u.dwId) != BattlefieldData.BattlefieldTeams.Wolves) { u.Buffs.OnStatChangeByMobSkill(MasterManager.MobSkillTemplates[123][15], 0, 0); } }); break; case 5: Parent.Field.BroadcastNotice("The Sheep have momentarily weakened."); bf.Users.ForEach(u => { if (bf.GetPlayerTeam(u.dwId) != BattlefieldData.BattlefieldTeams.Wolves) { u.Buffs.OnStatChangeByMobSkill(MasterManager.MobSkillTemplates[122][12], 0, 0); } }); break; } } } else { if (Parent.Field.Template.HasStatChangeItemLimit()) { Parent.SendMessage("Not allowed in this map."); return; } var newBuff = new BuffConsume(nItemID); newBuff.GenerateConsumeable(Parent); // buff gets added in the generator if it has bufftime } } InventoryManipulator.RemoveFrom(Parent, InventoryType.Consume, nPOS); // remove regardless }
public void UseMagnifyingGlass(short nMagnifyingPOS, short nEquipPOS) { if (Parent.Stats.nHP <= 0) { return; } var pTemplate = InventoryManipulator.GetItem(Parent, InventoryType.Consume, nMagnifyingPOS).Template as ConsumeItemTemplate; var pEquip = InventoryManipulator.GetItem(Parent, InventoryType.Equip, nEquipPOS) as GW_ItemSlotEquip; if (pEquip is null || pTemplate is null) { return; } if (pEquip.HasVisiblePotential) { return; } if (pEquip.nGrade == PotentialGradeCode.Normal) { return; } if (pEquip.CashItem) { return; } if (!ItemLogic.MagnifyingGlass(pTemplate.TemplateId)) { return; } if (pEquip.EquipTemplate.ReqLevel > ItemConstants.GlassRevealLevel(pTemplate.TemplateId)) { return; } if (pEquip.nOption1 == 0) { pEquip.nGrade = PotentialGradeCode.Visible_Rare; // cant get epic on first reveal } else { switch (pEquip.nGrade) { case PotentialGradeCode.Hidden_Rare: if (Constants.Rand.NextDouble() < RateConstants.ItemPotential_EpicOdds) { pEquip.nGrade = PotentialGradeCode.Visible_Epic; } else { pEquip.nGrade = PotentialGradeCode.Visible_Rare; } break; case PotentialGradeCode.Hidden_Epic: if (Constants.Rand.NextDouble() < RateConstants.ItemPotential_UniqueOdds) { pEquip.nGrade = PotentialGradeCode.Visible_Unique; } else { pEquip.nGrade = PotentialGradeCode.Visible_Epic; } break; case PotentialGradeCode.Hidden_Unique: pEquip.nGrade = PotentialGradeCode.Visible_Unique; break; } } var potentialCollection = MasterManager.ItemOptionTemplates .GetAll() .Where(p => p.ReqLevel <= pEquip.EquipTemplate.ReqLevel && // throw out incorrect level range ItemConstants.OptionTypeFitsEquipType(pEquip.nItemID, p.OptionType) && // throw out incorrect equip types ItemConstants.OptionGradeFitsEquipGrade(p.TemplateId, pEquip.nGrade) && // throw out incorrect grade codes p.OptionType != 90 // these show "Hidden" for some reason o___o ); var itemOptionTemplates = potentialCollection as ItemOptionTemplate[] ?? potentialCollection.ToArray(); if (itemOptionTemplates.Length <= 3) { throw new IndexOutOfRangeException($"unable to put potential on item. CID: {Parent.dwId} | EPOS: {nEquipPOS} | Grade: {nameof(pEquip.nGrade)} | Level: {pEquip.EquipTemplate.ReqLevel}"); } var lines = new List <int> { itemOptionTemplates.Random().TemplateId, itemOptionTemplates.Random().TemplateId }; lines.Sort(); // so the potential grades are in order if (pEquip.nOption3 == 0 || pEquip.nOption1 == 0) { var odds = pEquip.nOption1 == 0 ? RateConstants.ItemPotential_ThirdLineFirstReveal : RateConstants.ItemPotential_ThirdLineOdds; // lower odds for third line on first reveal if (Constants.Rand.NextDouble() < odds) { pEquip.nOption3 = (short)lines[0]; } } else // option1 > 0 && option3 != 0 { pEquip.nOption3 = (short)lines[0]; } pEquip.nOption2 = (short)lines[1]; // recalculate to ensure the first option is always the same grade as the equip pEquip.nOption1 = (short)itemOptionTemplates .Where(p => ItemConstants.GradeCodeByID(p.TemplateId) == pEquip.nGrade && p.TemplateId >= lines[1]).Random() .TemplateId; pEquip.sTitle = $"{pEquip.nOption1}|{pEquip.nOption2}"; Parent.Modify.Inventory(ctx => { ctx.UpdateEquipInformation(pEquip, nEquipPOS); }); InventoryManipulator.RemoveFrom(Parent, InventoryType.Consume, nMagnifyingPOS); Parent.SendPacket(pEquip.ShowItemReleaseEffect(Parent.dwId, nEquipPOS)); }
public void UseUpgradeScroll(short nScrollPOS, short nEquipPOS, bool bWhiteScroll) { if (Parent.Stats.nHP <= 0) { return; } var pScrollTemplate = InventoryManipulator.GetItem(Parent, InventoryType.Consume, nScrollPOS).Template as ConsumeItemTemplate; var pEquip = InventoryManipulator.GetItem(Parent, InventoryType.Equip, nEquipPOS) as GW_ItemSlotEquip; var nWhiteScrollPOS = InventoryManipulator.GetAnyItem(Parent, InventoryType.Consume, ItemConstants.WhiteScroll).Item1; if (pEquip == null || pScrollTemplate == null) { return; } if (pEquip.CashItem) { return; } if (pEquip.RemainingUpgradeCount <= 0 && pScrollTemplate.Recover <= 0) { return; } var bSuccess = pScrollTemplate.ScrollSuccess(Constants.Rand); var bDestroy = !bSuccess && pScrollTemplate.ScrollDestroy(Constants.Rand); bWhiteScroll = bWhiteScroll && nWhiteScrollPOS > 0; if (!ItemConstants.is_correct_upgrade_equip(pScrollTemplate.TemplateId, pEquip.nItemID)) // PE, validated client-side { return; } if (bSuccess) { if (pScrollTemplate.Recover > 0) { pEquip.RemainingUpgradeCount += (byte)pScrollTemplate.Recover; } else { if (pScrollTemplate.PreventSlip) { pEquip.nAttribute |= ItemAttributeFlags.Spikes; } else if (pScrollTemplate.WarmSupport) { pEquip.nAttribute |= ItemAttributeFlags.Cold; } else if (pScrollTemplate.RandStat) { var randRange = 2 + (2 * pScrollTemplate.IncRandVol); var gX = new GaussianRandom(); if (pEquip.niSTR > 0) { pEquip.niSTR = (short)Math.Max(0, gX.GaussianDistributionVariation(pEquip.niSTR, randRange, false)); } if (pEquip.niLUK > 0) { pEquip.niLUK = (short)Math.Max(0, gX.GaussianDistributionVariation(pEquip.niLUK, randRange, false)); } if (pEquip.niINT > 0) { pEquip.niINT = (short)Math.Max(0, gX.GaussianDistributionVariation(pEquip.niINT, randRange, false)); } if (pEquip.niDEX > 0) { pEquip.niDEX = (short)Math.Max(0, gX.GaussianDistributionVariation(pEquip.niDEX, randRange, false)); } if (pEquip.niACC > 0) { pEquip.niACC = (short)Math.Max(0, gX.GaussianDistributionVariation(pEquip.niACC, randRange, false)); } if (pEquip.niEVA > 0) { pEquip.niEVA = (short)Math.Max(0, gX.GaussianDistributionVariation(pEquip.niEVA, randRange, false)); } if (pEquip.niMaxHP > 0) { pEquip.niMaxHP = (short)Math.Max(0, gX.GaussianDistributionVariation(pEquip.niMaxHP, randRange, false)); } if (pEquip.niMaxMP > 0) { pEquip.niMaxMP = (short)Math.Max(0, gX.GaussianDistributionVariation(pEquip.niMaxMP, randRange, false)); } if (pEquip.niPAD > 0) { pEquip.niPAD = (short)Math.Max(0, gX.GaussianDistributionVariation(pEquip.niPAD, randRange, false)); } if (pEquip.niMAD > 0) { pEquip.niMAD = (short)Math.Max(0, gX.GaussianDistributionVariation(pEquip.niMAD, randRange, false)); } if (pEquip.niPDD > 0) { pEquip.niPDD = (short)Math.Max(0, gX.GaussianDistributionVariation(pEquip.niPDD, randRange, false)); } if (pEquip.niMDD > 0) { pEquip.niMDD = (short)Math.Max(0, gX.GaussianDistributionVariation(pEquip.niMDD, randRange, false)); } if (pEquip.niSpeed > 0) { pEquip.niSpeed = (short)Math.Max(0, gX.GaussianDistributionVariation(pEquip.niSpeed, randRange, false)); } if (pEquip.niJump > 0) { pEquip.niJump = (short)Math.Max(0, gX.GaussianDistributionVariation(pEquip.niJump, randRange, false)); } } else { pEquip.niSTR += (short)pScrollTemplate.IncSTR; pEquip.niLUK += (short)pScrollTemplate.IncLUK; pEquip.niINT += (short)pScrollTemplate.IncINT; pEquip.niDEX += (short)pScrollTemplate.IncDEX; pEquip.niMaxHP += (short)pScrollTemplate.IncMHP; pEquip.niMaxMP += (short)pScrollTemplate.IncMMP; pEquip.niPAD += (short)pScrollTemplate.IncPAD; // watk pEquip.niMAD += (short)pScrollTemplate.IncMAD; // matk pEquip.niPDD += (short)pScrollTemplate.IncPDD; // wdef pEquip.niMDD += (short)pScrollTemplate.IncMDD; // mdef pEquip.niACC += (short)pScrollTemplate.IncACC; // accuracy pEquip.niEVA += (short)pScrollTemplate.IncEVA; // avoid pEquip.niCraft += (short)pScrollTemplate.IncCraft; // still not sure wtf this is pEquip.niSpeed += (short)pScrollTemplate.IncSpeed; pEquip.niJump += (short)pScrollTemplate.IncJump; } } } if (bDestroy) { InventoryManipulator.RemoveFrom(Parent, InventoryType.Equip, nEquipPOS); } else // success or fail { if (pScrollTemplate.Recover <= 0) // not an upgrade count recovery scroll { pEquip.RemainingUpgradeCount -= 1; // reduce remaining upgrade count if no white scroll if (bSuccess) { pEquip.CurrentUpgradeCount += 1; // increase upgrade count } else if (bWhiteScroll) { pEquip.RemainingUpgradeCount += 1; } if (bWhiteScroll) { InventoryManipulator.RemoveFrom(Parent, InventoryType.Consume, nWhiteScrollPOS); } } Parent.Modify.Inventory(ctx => { ctx.UpdateEquipInformation(pEquip, nEquipPOS); }); } InventoryManipulator.RemoveFrom(Parent, InventoryType.Consume, nScrollPOS); Parent.StatisticsTracker.IncrementScrollUse(pScrollTemplate.TemplateId, bSuccess, bDestroy); Parent.Field.Broadcast(pEquip.ShowItemUpgradeEffect(Parent, bSuccess, bDestroy, bWhiteScroll)); }