/// <summary> /// Move an item from the character's account cash locker to the character's storage. /// </summary> /// <param name="c"></param> /// <param name="p"></param> public static void MoveLToS(WvsShopClient c, CInPacket p) { if (p.Available < 8) { return; } var sn = p.Decode8(); var cashItem = c.CashLocker.GetBySN(sn); // unable to find item if (cashItem == null) { return; } var nTargetSlot = InventoryManipulator.InsertInto(c.Character, cashItem.Item); // item insertion failed if (nTargetSlot == 0) { return; // TODO proper error code/response } c.CashLocker.Remove(cashItem); c.SendPacket(CPacket.CCashShop.MoveLtoSResponse(cashItem, nTargetSlot)); }
public static void IncCharSlotCount(WvsShopClient c, CInPacket p) { // validate packet length if (p.Available < 9) { return; } p.Decode1(); var cashType = p.Decode4(); var commodityId = p.Decode4(); //Log.Debug("CASH COMMODITY ID: " + commodityId); if (!c.Account.HasCash((CashType)cashType, 6900) || (c.Account.AccountData.CharacterSlots + 3) > #if DEBUG 27 #else Constants.MaxCharSlot #endif ) { c.SendPacket(CPacket.CCashShop.RequestFailPacket(CashItemOps.CashItemRes_Buy_Failed, CashItemFailed.PurchaseLimitOver)); }
public static COutPacket EnableShopActions(WvsShopClient c) { var p = new COutPacket(SendOps.LP_CashShopQueryCashResult); p.Encode4(c.Account.AccountData.NX_Credit); // nx cash p.Encode4(c.Account.AccountData.NX_Maplepoint); // maple point p.Encode4(c.Account.AccountData.NX_Prepaid); // prepaid nx return(p); }
/// <summary> /// Client sends an updated wish list when something is changed. /// Wish list max size is 10. /// Client expects to receive a full wish list packet back. /// </summary> /// <param name="c"></param> /// <param name="p"></param> public static void ModifyWishList(WvsShopClient c, CInPacket p) { if (p.Available < 40) { return; } c.Character.Stats.WishList = p.DecodeIntArray(10); c.SendPacket(CPacket.CCashShop.WishListData(c, true)); c.EnableActions(); }
/** * Client sends cash item SN. * We index cash items by their serial number. * WZ files indexes cash items by a commodity ID. * The commodity ID (~12000 total) is not used for anything. */ public static void Buy(WvsShopClient c, CInPacket p) { // validate packet length if (p.Available < 9) { return; } p.Decode1(); // 00 var cashType = (CashType)p.Decode4(); var nCommoditySN = p.Decode4(); var commodityInfo = MasterManager.CommodityProvider[nCommoditySN]; if (commodityInfo == null) { return; } if (!commodityInfo.OnSale) { return; // TODO proper error code/response } var item = MasterManager.CreateCashCommodityItem(nCommoditySN); if (item is null) { return; } if (!c.Account.HasCash(cashType, item.NXCost)) { return; // TODO proper error code/response } if (ItemConstants.IsPet(item.nItemID) && InventoryManipulator.GetItemByCashSN(c.Character, InventoryType.Cash, item.SN).Item2 != null) { return; // cant have two of the same pet cuz it screws up our indexing } c.CashLocker.Add(item); #if DEBUG c.Account.ModifyCash(cashType, 10000); Log.Info($"{commodityInfo.CashItemSN}"); #else c.Account.ModifyCash(cashType, -commodityInfo.Price); #endif item.dwAccountID = c.Account.ID; item.dwCharacterID = c.dwCharId; c.SendPacket(CPacket.CCashShop.BuyResponse(item)); // do best items/limited goods handling here }
public static COutPacket WishListData(WvsShopClient c, bool update) { var p = new COutPacket(SendOps.LP_CashShopCashItemResult); p.Encode1((byte)(update ? CashItemOps.CashItemRes_SetWish_Done : CashItemOps.CashItemRes_LoadWish_Done)); for (int i = 0; i < 10; i++) // wishlist is always int[10] { p.Encode4(c.Character.Wishlist[i]); } return(p); }
/** * Cash packages have data in both the Commodity and Package section of Etc.wz * Client sends package SN which is stored in the commodity section of WZ files (one of the ~12000 entries) * The commodity itemid (not SN) contains the SN for the CashPackage * The CashPackage (one of ~450) contains the cash item SN's of the package items */ public static void BuyPackage(WvsShopClient c, CInPacket p) { if (p.Available < 9) { return; } p.Decode1(); // 00 var cashType = (CashType)p.Decode4(); var nCommoditySN = p.Decode4(); var commodityInfo = MasterManager.CommodityProvider[nCommoditySN]; if (commodityInfo is null) { return; } if (!commodityInfo.OnSale) { return; // TODO proper error code/response } if (!c.Account.HasCash(cashType, commodityInfo.Price)) { return; // TODO proper error code/response } var packagedata = MasterManager.CreateCashPackageItems(commodityInfo.ItemID); packagedata.ForEach(item => { item.dwAccountID = c.Account.ID; item.dwCharacterID = c.dwCharId; }); #if RELEASE c.Account.ModifyCash(cashType, -commodityInfo.Price); #else foreach (var item in packagedata) { item.dwAccountID = c.Account.ID; item.dwCharacterID = c.dwCharId; c.Account.AccountData.Locker.Add(item); } Log.Info($"================COMMODITYSN {nCommoditySN}"); // temporary so i can quickly find a buncha serial numbers return; #endif c.SendPacket(CPacket.CCashShop.BuyPackageResponse(packagedata)); }
public static COutPacket LockerData(WvsShopClient c) { var p = new COutPacket(SendOps.LP_CashShopCashItemResult); var data = c.Account.AccountData; p.Encode1((byte)CashItemOps.CashItemRes_LoadLocker_Done); p.Encode2((short)data.Locker.Count); foreach (var item in data.Locker) // m_aCashItemInfo { data.Locker.EncodeItem(item, p); // CInPacket::DecodeBuffer(v2, v3->m_aCashItemInfo.a, 55 * v4); } p.Encode2(data.Locker.SlotMax); // m_nTrunkCount p.Encode2((short)data.CharacterSlots); // m_nCharacterSlotCount p.Encode2((short)(data.CharacterSlots - 3)); // m_nBuyCharacterCount p.Encode2((short)c.Account.LoadCharIdList().Count); // m_nCharacterCount return(p); }
/// <summary> /// Move an item from the character's storage to the character's account cash locker /// </summary> /// <param name="c"></param> /// <param name="p"></param> public static void MoveSToL(WvsShopClient c, CInPacket p) { if (p.Available < 9) { return; } var cashCommodityId = p.Decode8(); var nTI = (InventoryType)p.Decode1(); var(itemSlot, item) = InventoryManipulator.GetItemByCashSN(c.Character, nTI, cashCommodityId); // unable to find item in inventory if (item is null) { return; } if (ItemConstants.IsRing(item.nItemID)) { c.SendPacket(CPacket.CCashShop.RequestFailPacket(CashItemOps.CashItemRes_MoveStoL_Failed, CashItemFailed.NotAvailableTime)); return; } var newItem = MasterManager.CreateCashCommodityItem(item.liCashItemSN); newItem.Item.nNumber = item.nNumber; newItem.Item.liSN = item.liSN; newItem.Item.tDateExpire = item.tDateExpire; //newItem.dwCharacterID = // TODO newItem.dwAccountID = c.Character.Account.ID; c.CashLocker.Add(newItem); InventoryManipulator.RemoveFrom(c.Character, nTI, itemSlot, -1); c.SendPacket(CPacket.CCashShop.MoveSToLResponse(c.CashLocker, newItem)); }
public static void IncTrunkCount(WvsShopClient c, CInPacket p) { // storage space increase }
public static void GiftPackage(WvsShopClient c, CInPacket p) { // TODO }
public CouponCode(string code, WvsShopClient c) { if (code.Length > 16) { return; } IncorrectAccount = true; Expired = true; Invalid = true; Used = true; Client = c; Code = code; // --------------- DB Tables To Load // coupon_code <- check this to see if coupon exists // acc_created_for <- is coupon locked to a specific account // char_used_by <- has coupon been used // nx_amount // nx_items using (var conn = new NpgsqlConnection(Constants.DB_World0_ConString)) { conn.Open(); var select = $"SELECT acc_created_for, char_used_by, nx_amount, nx_items, expiration " + $"FROM {Constants.DB_All_World_Schema_Name}.cs_coupon_codes " + $"WHERE coupon_code = @code"; using (var cmd = new NpgsqlCommand(select, conn)) { cmd.Parameters.AddWithValue("code", Code); using (var r = cmd.ExecuteReader()) while (r.Read()) { Invalid = false; if (r.GetInt32(0) == c.Account.ID || r.GetInt32(0) <= 0) { IncorrectAccount = false; } if (r.GetInt32(1) <= 0) { Used = false; } try { // seems to throw error when value is null so wrapping it in try-catch to avoid that if (r.GetTimeStamp(4) >= NpgsqlDateTime.Now) { Expired = false; } } catch { Expired = false; } NX = r.GetInt32(2); Items = r.GetValue(3) as int[]; } } } }