/** * 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 }
/// <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)); }
private void LoadFromDB() { if (WorldID != 0) { throw new Exception("Unhandled world ID in WorldAccountData."); } using (var conn = new NpgsqlConnection(Constants.DB_World0_ConString)) { conn.Open(); using (var cmd = new NpgsqlCommand( $"SELECT * FROM {Constants.DB_All_World_Schema_Name}.account_locker_items WHERE account_id = {AccountID};", conn)) using (var r = cmd.ExecuteReader()) { while (r.Read()) { var cs_sn = Convert.ToInt64(r["item_cash_serial_number"]); var commodity = MasterManager.CreateCashCommodityItem(cs_sn); commodity.dwAccountID = AccountID; commodity.dwCharacterID = Convert.ToInt32(r["purchase_character"]); commodity.Item.tDateExpire = (DateTime)r["item_date_expire"]; commodity.Item.nNumber = Convert.ToInt16(r["item_quantity"]); commodity.Item.liSN = Convert.ToInt64(r["item_serial_number"]); commodity.BuyerCharName = r["purchase_name"] as string ?? string.Empty; Locker.Add(commodity); } } using (var cmd = new NpgsqlCommand( $"SELECT * FROM {Constants.DB_All_World_Schema_Name}.account_data WHERE account_id = {AccountID};", conn)) using (var r = cmd.ExecuteReader()) { if (r.Read()) { CharacterSlots = (int)r["character_slots"]; Admin = (int)r["admin"]; NX_Credit = (int)r["nx_credit"]; NX_Maplepoint = (int)r["nx_maplepoint"]; NX_Prepaid = (int)r["nx_prepaid"]; } else { #if DEBUG CharacterSlots = 12; Admin = 1; NX_Credit = 50000; NX_Maplepoint = 50000; NX_Prepaid = 50000; #else CharacterSlots = BaseCharSlots; Admin = 0; NX_Credit = 0; NX_Maplepoint = 0; NX_Prepaid = 0; #endif } } } }