правки для магазина

This commit is contained in:
2026-07-19 19:13:50 +04:00
parent 58dcb622f3
commit 737d7c756d
3 changed files with 109 additions and 57 deletions
+2 -2
View File
@@ -144,7 +144,7 @@ function SHOP_UI.MainFrame_Create()
shopFrame.Title:SetFont("Fonts\\FRIZQT__.TTF", 14) shopFrame.Title:SetFont("Fonts\\FRIZQT__.TTF", 14)
shopFrame.Title:SetShadowOffset(1, -1) shopFrame.Title:SetShadowOffset(1, -1)
shopFrame.Title:SetPoint("TOP", shopFrame, "TOP", 0, -3) shopFrame.Title:SetPoint("TOP", shopFrame, "TOP", 0, -3)
shopFrame.Title:SetText("|cffedd100Shop|r") shopFrame.Title:SetText("|cffedd100Лавка Лунной Жрицы|r")
-- create navigation button placeholders, pass parent as arg -- create navigation button placeholders, pass parent as arg
SHOP_UI.NavButtons_Create(shopFrame) SHOP_UI.NavButtons_Create(shopFrame)
@@ -1193,7 +1193,7 @@ local function ModifyGameMenuFrame()
storeButton.Text:SetFont("Fonts\\FRIZQT__.TTF", 13, "OUTLINE") storeButton.Text:SetFont("Fonts\\FRIZQT__.TTF", 13, "OUTLINE")
storeButton.Text:SetShadowOffset(1, -1) storeButton.Text:SetShadowOffset(1, -1)
storeButton.Text:SetPoint("CENTER", storeButton, "CENTER", 0, 1) storeButton.Text:SetPoint("CENTER", storeButton, "CENTER", 0, 1)
storeButton.Text:SetText("|cffdbe005Store"); storeButton.Text:SetText("|cffdbe005Лавка Лунной Жрицы");
-- on click open the shop frame and hide the escape menu -- on click open the shop frame and hide the escape menu
storeButton:SetScript("OnClick", function() storeButton:SetScript("OnClick", function()
+58 -53
View File
@@ -7,7 +7,7 @@ local CONFIG = {
mailSenderGUID = 1, -- GUID of the character shown as sender of purchase mails mailSenderGUID = 1, -- GUID of the character shown as sender of purchase mails
strings = { strings = {
-- Currency name is appended to the end of this string -- Currency name is appended to the end of this string
insufficientFunds = "You don't have enough", insufficientFunds = "Недостаточно средств на балансе",
-- Type is appended, ie. title, mount, pet etc. -- Type is appended, ie. title, mount, pet etc.
alreadyKnown = "You already have this", alreadyKnown = "You already have this",
tooHighLevel = "Your level is too high", tooHighLevel = "Your level is too high",
@@ -22,11 +22,24 @@ local CONFIG = {
local AIO = AIO or require("AIO") and require("Store_DataStruct") local AIO = AIO or require("AIO") and require("Store_DataStruct")
local CURRENCY_TYPES = { local CURRENCY_TYPES = {
[1] = "GOLD",
[2] = "ITEM_TOKEN",
[3] = "SERVER_HANDLED" [3] = "SERVER_HANDLED"
} }
local purchaseReferenceSequence = 0
local function GetAccountBalance(player)
local query = AuthDBQuery(
"SELECT CAST(`balance` AS DOUBLE) FROM `account_balances` WHERE `account_id` = " ..
player:GetAccountId() .. " LIMIT 1;"
)
if not query then
return 0
end
return query:GetDouble(0)
end
local SHOP_UI = { local SHOP_UI = {
serviceHandlers = { serviceHandlers = {
[1] = "ItemHandler", -- Okay [1] = "ItemHandler", -- Okay
@@ -55,17 +68,8 @@ function StoreHandler.UpdateCurrencies(player)
local val = 0 local val = 0
local currencyTypeText = CURRENCY_TYPES[currency[KEYS.currency.currencyType]] local currencyTypeText = CURRENCY_TYPES[currency[KEYS.currency.currencyType]]
-- Handle the different currency types
if(currencyTypeText == "GOLD") then
val = math.floor(player:GetCoinage() / 10000)
end
if(currencyTypeText == "ITEM_TOKEN") then
val = player:GetItemCount(currency[KEYS.currency.data])
end
if(currencyTypeText == "SERVER_HANDLED") then if(currencyTypeText == "SERVER_HANDLED") then
-- Add your custom handling here for retreiving your server handled currencies val = GetAccountBalance(player)
end end
-- If value is larger than 10k then truncate to make sure it fits within the shop frame -- If value is larger than 10k then truncate to make sure it fits within the shop frame
@@ -73,7 +77,9 @@ function StoreHandler.UpdateCurrencies(player)
val = "9999+" val = "9999+"
end end
table.insert(tmp, val) -- Preserve the database currency id. A positional array silently breaks as
-- soon as ids have gaps or are reordered by MySQL.
tmp[currencyId] = val
end end
AIO.Handle(player, "STORE_CLIENT", "UpdateCurrencies", tmp) AIO.Handle(player, "STORE_CLIENT", "UpdateCurrencies", tmp)
end end
@@ -106,39 +112,38 @@ function StoreHandler.Purchase(player, serviceId)
end end
-- Helper functions -- Helper functions
function SHOP_UI.DeductCurrency(player, currencyId, amount) function SHOP_UI.DeductCurrency(player, currencyId, amount, serviceId)
local currency = GetCurrencyData() local currency = GetCurrencyData()
local currencyType = currency[currencyId][KEYS.currency.currencyType] if not currency[currencyId] then
local currencyName = currency[currencyId][KEYS.currency.name]
local currencyData = currency[currencyId][KEYS.currency.data]
-- Gold handling
if(CURRENCY_TYPES[currencyType] == "GOLD") then
if(player:GetCoinage() < amount * 10000) then
player:SendAreaTriggerMessage("|cFFFF0000"..CONFIG.strings.insufficientFunds.." "..currencyName.."|r")
player:PlayDirectSound(GetSoundEffect("notEnoughMoney", player:GetRace(), player:GetGender()), player)
return false
end
player:SetCoinage(player:GetCoinage() - (amount * 10000))
end
-- Token handling
if(CURRENCY_TYPES[currencyType] == "ITEM_TOKEN") then
if not(player:HasItem(currencyData, amount)) then
player:SendAreaTriggerMessage("|cFFFF0000"..CONFIG.strings.insufficientFunds.." "..currencyName.."|r")
player:PlayDirectSound(GetSoundEffect("notEnoughMoney", player:GetRace(), player:GetGender()), player)
return false
end
player:RemoveItem(currencyData, amount)
end
-- Other special handlingm you have to add your own integration here.
if(CURRENCY_TYPES[currencyType] == "SERVER_HANDLED") then
return false return false
end end
local currencyType = currency[currencyId][KEYS.currency.currencyType]
if CURRENCY_TYPES[currencyType] ~= "SERVER_HANDLED" then
return false
end
purchaseReferenceSequence = purchaseReferenceSequence + 1
local reference = string.format(
"game-store:%u:%u:%u:%u:%u",
player:GetAccountId(),
player:GetGUIDLow(),
serviceId or 0,
os.time(),
purchaseReferenceSequence
)
local result = AuthDBQuery(
"SELECT `store_deduct_balance`(" .. player:GetAccountId() .. ", " .. amount .. ", '" .. reference .. "', " ..
player:GetGUIDLow() .. ", " .. (serviceId or 0) .. ") AS `balance_after`;"
)
local balanceAfter = result and result:GetDouble(0) or -1
if balanceAfter < 0 then
player:SendAreaTriggerMessage("|cFFFF0000" .. CONFIG.strings.insufficientFunds .. "|r")
player:PlayDirectSound(GetSoundEffect("notEnoughMoney", player:GetRace(), player:GetGender()), player)
return false
end
return true return true
end end
@@ -152,7 +157,7 @@ function SHOP_UI.ItemHandler(player, data)
local currency, amount = data[KEYS.service.currency], data[KEYS.service.price] - data[KEYS.service.discount] local currency, amount = data[KEYS.service.currency], data[KEYS.service.price] - data[KEYS.service.discount]
-- Deduct currency -- Deduct currency
local deducted = SHOP_UI.DeductCurrency(player, currency, amount) local deducted = SHOP_UI.DeductCurrency(player, currency, amount, data.ID)
-- If currency was not deducted from the player, abort and send message -- If currency was not deducted from the player, abort and send message
if not(deducted) then if not(deducted) then
@@ -178,7 +183,7 @@ function SHOP_UI.GoldHandler(player, data)
local currency, amount = data[KEYS.service.currency], data[KEYS.service.price] - data[KEYS.service.discount] local currency, amount = data[KEYS.service.currency], data[KEYS.service.price] - data[KEYS.service.discount]
-- Deduct currency -- Deduct currency
local deducted = SHOP_UI.DeductCurrency(player, currency, amount) local deducted = SHOP_UI.DeductCurrency(player, currency, amount, data.ID)
-- If currency was not deducted from the player, abort and send message -- If currency was not deducted from the player, abort and send message
if not(deducted) then if not(deducted) then
@@ -212,7 +217,7 @@ function SHOP_UI.MountHandler(player, data)
end end
-- Deduct currency -- Deduct currency
local deducted = SHOP_UI.DeductCurrency(player, currency, amount) local deducted = SHOP_UI.DeductCurrency(player, currency, amount, data.ID)
-- If currency was not deducted from the player, abort and send message -- If currency was not deducted from the player, abort and send message
if not(deducted) then if not(deducted) then
@@ -250,7 +255,7 @@ function SHOP_UI.PetHandler(player, data)
end end
-- Deduct currency -- Deduct currency
local deducted = SHOP_UI.DeductCurrency(player, currency, amount) local deducted = SHOP_UI.DeductCurrency(player, currency, amount, data.ID)
-- If currency was not deducted from the player, abort and send message -- If currency was not deducted from the player, abort and send message
if not(deducted) then if not(deducted) then
@@ -271,7 +276,7 @@ function SHOP_UI.BuffHandler(player, data)
local currency, amount = data[KEYS.service.currency], data[KEYS.service.price] - data[KEYS.service.discount] local currency, amount = data[KEYS.service.currency], data[KEYS.service.price] - data[KEYS.service.discount]
-- Deduct currency -- Deduct currency
local deducted = SHOP_UI.DeductCurrency(player, currency, amount) local deducted = SHOP_UI.DeductCurrency(player, currency, amount, data.ID)
-- If currency was not deducted from the player, abort and send message -- If currency was not deducted from the player, abort and send message
if not(deducted) then if not(deducted) then
@@ -292,7 +297,7 @@ function SHOP_UI.ServiceHandler(player, data)
local currency, amount = data[KEYS.service.currency], data[KEYS.service.price] - data[KEYS.service.discount] local currency, amount = data[KEYS.service.currency], data[KEYS.service.price] - data[KEYS.service.discount]
-- Deduct currency -- Deduct currency
local deducted = SHOP_UI.DeductCurrency(player, currency, amount) local deducted = SHOP_UI.DeductCurrency(player, currency, amount, data.ID)
-- If currency was not deducted from the player, abort and send message -- If currency was not deducted from the player, abort and send message
if not(deducted) then if not(deducted) then
@@ -319,7 +324,7 @@ function SHOP_UI.LevelHandler(player, data)
end end
-- Deduct currency -- Deduct currency
local deducted = SHOP_UI.DeductCurrency(player, currency, amount) local deducted = SHOP_UI.DeductCurrency(player, currency, amount, data.ID)
-- If currency was not deducted from the player, abort and send message -- If currency was not deducted from the player, abort and send message
if not(deducted) then if not(deducted) then
@@ -354,7 +359,7 @@ function SHOP_UI.TitleHandler(player, data)
end end
-- Deduct currency -- Deduct currency
local deducted = SHOP_UI.DeductCurrency(player, currency, amount) local deducted = SHOP_UI.DeductCurrency(player, currency, amount, data.ID)
-- If currency was not deducted from the player, abort and send message -- If currency was not deducted from the player, abort and send message
if not(deducted) then if not(deducted) then
@@ -372,4 +377,4 @@ function SHOP_UI.UnusedHandler(player, data)
-- Since this is unused, always return false until the function is in use. -- Since this is unused, always return false until the function is in use.
return false return false
end end
+49 -2
View File
@@ -73,8 +73,15 @@ CREATE TABLE IF NOT EXISTS `store_currencies` (
-- Dumping data for table store.store_currencies: ~2 rows (approximately) -- Dumping data for table store.store_currencies: ~2 rows (approximately)
INSERT INTO `store_currencies` (`id`, `type`, `name`, `icon`, `data`, `tooltip`) VALUES INSERT INTO `store_currencies` (`id`, `type`, `name`, `icon`, `data`, `tooltip`) VALUES
(1, 1, 'Gold', 'Gold', 0, 'This is normal gold.'), (1, 3, 'Баланс', 'Gold', 0, 'Баланс учётной записи на сайте.');
(2, 2, 'Item Token', 'Token', 4540, 'This is an item currency.');
-- The website account balance is the only in-game store currency. These
-- statements also migrate databases bootstrapped by an older Store.sql.
UPDATE `store_currencies`
SET `type` = 3, `name` = 'Баланс', `icon` = 'Gold', `data` = 0,
`tooltip` = 'Баланс учётной записи на сайте.'
WHERE `id` = 1;
DELETE FROM `store_currencies` WHERE `id` <> 1;
-- Dumping structure for table store.store_logs -- Dumping structure for table store.store_logs
CREATE TABLE IF NOT EXISTS `store_logs` ( CREATE TABLE IF NOT EXISTS `store_logs` (
@@ -173,6 +180,46 @@ INSERT INTO `store_services` (`id`, `type`, `name`, `tooltipName`, `tooltipType`
(17, 8, 'Level 60 Boost', 'Level Boost', '', 'Boosts your characters level to level 60!', 'achievement_level_60', 40, 1, 0, 0, 0, 1, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1), (17, 8, 'Level 60 Boost', 'Level Boost', '', 'Boosts your characters level to level 60!', 'achievement_level_60', 40, 1, 0, 0, 0, 1, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1),
(18, 1, 'Tuxedo Set', 'Tuxedo Set', '', 'Express your great fashion sense with this full Tuxedo set!\r\n\r\nContains the following:\r\n\r\n1x Tuxedo Jacket\r\n1x Tuxedo Shirt\r\n1x Tuxedo Pants', 'inv_shirt_black_01', 50, 1, 0, 0, 0, 1, 10036, 10035, 10034, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1); (18, 1, 'Tuxedo Set', 'Tuxedo Set', '', 'Express your great fashion sense with this full Tuxedo set!\r\n\r\nContains the following:\r\n\r\n1x Tuxedo Jacket\r\n1x Tuxedo Shirt\r\n1x Tuxedo Pants', 'inv_shirt_black_01', 50, 1, 0, 0, 0, 1, 10036, 10035, 10034, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1);
UPDATE `store_services` SET `currency` = 1;
-- Atomic bridge between the website balance and Eluna. It both reserves the
-- funds and writes the website-compatible ledger entry before a reward is sent.
DROP FUNCTION IF EXISTS `acore_auth`.`store_deduct_balance`;
DELIMITER //
CREATE FUNCTION `acore_auth`.`store_deduct_balance`(
p_account_id INT UNSIGNED,
p_amount DECIMAL(14,2),
p_reference VARCHAR(191),
p_character_guid INT UNSIGNED,
p_service_id INT UNSIGNED
) RETURNS DECIMAL(14,2)
DETERMINISTIC
MODIFIES SQL DATA
BEGIN
DECLARE v_balance_after DECIMAL(14,2) DEFAULT -1;
UPDATE `acore_auth`.`account_balances`
SET `balance` = `balance` - p_amount, `updated_at` = CURRENT_TIMESTAMP
WHERE `account_id` = p_account_id
AND p_amount >= 0
AND `balance` >= p_amount;
IF ROW_COUNT() = 1 THEN
SELECT `balance` INTO v_balance_after
FROM `acore_auth`.`account_balances`
WHERE `account_id` = p_account_id;
INSERT INTO `acore_auth`.`balance_transactions`
(`account_id`, `type`, `amount`, `balance_after`, `reference`, `metadata`, `created_at`)
VALUES
(p_account_id, 'store_purchase', -p_amount, v_balance_after, p_reference,
JSON_OBJECT('character_guid', p_character_guid, 'service_id', p_service_id), CURRENT_TIMESTAMP);
END IF;
RETURN v_balance_after;
END//
DELIMITER ;
/*!40103 SET TIME_ZONE=IFNULL(@OLD_TIME_ZONE, 'system') */; /*!40103 SET TIME_ZONE=IFNULL(@OLD_TIME_ZONE, 'system') */;
/*!40101 SET SQL_MODE=IFNULL(@OLD_SQL_MODE, '') */; /*!40101 SET SQL_MODE=IFNULL(@OLD_SQL_MODE, '') */;
/*!40014 SET FOREIGN_KEY_CHECKS=IFNULL(@OLD_FOREIGN_KEY_CHECKS, 1) */; /*!40014 SET FOREIGN_KEY_CHECKS=IFNULL(@OLD_FOREIGN_KEY_CHECKS, 1) */;