493 lines
18 KiB
Lua
493 lines
18 KiB
Lua
--[[
|
||
Illarion Server
|
||
|
||
This program is free software: you can redistribute it and/or modify it under
|
||
the terms of the GNU Affero General Public License as published by the Free
|
||
Software Foundation, either version 3 of the License, or (at your option) any
|
||
later version.
|
||
|
||
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||
PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||
details.
|
||
|
||
You should have received a copy of the GNU Affero General Public License along
|
||
with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
]]
|
||
--- This script contains a set of helper methods to work with money in the game.
|
||
-- This functions should be used for any interaction with money.
|
||
--
|
||
-- Author: Martin Karing (Nitram)
|
||
local M = {}
|
||
|
||
--- The Item ID of the item used as gold coins.
|
||
local GoldCoinsID = 61
|
||
|
||
--- The Item ID of the item used as silver coins.
|
||
local SilverCoinsID = 3077
|
||
|
||
--- The Item ID of the item used as copper coins.
|
||
local CopperCoinsID = 3076
|
||
|
||
--- This method calculates the values of the 3 valid existing coin types (gold,
|
||
-- silver, copper) into a single value that represents the total money value
|
||
-- of the coins. It basically recalculates silver and gold coins to copper
|
||
-- coins in value and adds it to the copper coins and returns this value.
|
||
--
|
||
-- @param gCoins - number - the amount of gold coins
|
||
-- @param sCoins - number - the amount of silver coins
|
||
-- @param cCoins - number - the amount of copper coins
|
||
-- @return number - the total amount of the money in copper coins
|
||
function M.CoinsToMoney(gCoins, sCoins, cCoins)
|
||
return (gCoins * 100 + sCoins) * 100 + cCoins
|
||
end
|
||
|
||
--- This method returns the total amount of money in copper coins the char has
|
||
-- in his inventory. This method takes all three types of coins into
|
||
-- consideration.
|
||
--
|
||
-- @param char - CharStruct - the char the money count is wanted from
|
||
-- @return number - the total amount of money in copper coins the player has
|
||
function M.CharCoinsToMoney(char)
|
||
return M.CoinsToMoney(char:countItem(GoldCoinsID), char:countItem(SilverCoinsID), char:countItem(CopperCoinsID))
|
||
end
|
||
|
||
--- Get the coins a character has in his inventory.
|
||
--
|
||
-- @param char - CharStruct - the char the coins are wanted from
|
||
-- @return number - the amount of gold coins the character has
|
||
-- @return number - the amount of silver coins the character has
|
||
-- @return number - the amount of copper coins the character has
|
||
-- @note The values returned by this function are not normalized. So its
|
||
-- possible that the values for silver and copper coins are greater 100
|
||
function M.CharCoins(char)
|
||
return char:countItem(GoldCoinsID), char:countItem(SilverCoinsID), char:countItem(CopperCoinsID)
|
||
end
|
||
|
||
--- This method returns the total amount of money in copper coins the char has
|
||
-- in his depot. This method takes all three types of coins into
|
||
-- consideration.
|
||
--
|
||
-- @param char - CharStruct - the char the money count is wanted from
|
||
-- @param depNr - the ID of the depot to check
|
||
-- @return number - the total amount of money in copper coins the player has
|
||
function M.DepotCoinsToMoney(char, depNr)
|
||
local depot = char:getDepot(depNr)
|
||
if depot then
|
||
local copper = depot:countItem(CopperCoinsID)
|
||
local silver = depot:countItem(SilverCoinsID)
|
||
local gold = depot:countItem(GoldCoinsID)
|
||
return M.CoinsToMoney(gold, silver, copper)
|
||
else
|
||
return 0
|
||
end
|
||
end
|
||
|
||
--- Get the coins a character has in his Depot.
|
||
--
|
||
-- @param char - CharStruct - the char the money count is wanted from
|
||
-- @param depNr - the ID of the depot to check
|
||
-- @return number - the amount of gold coins the depot has
|
||
-- @return number - the amount of silver coins the depot has
|
||
-- @return number - the amount of copper coins the depot has
|
||
function M.DepotCoins(char, depNr)
|
||
local depot = char:getDepot(depNr)
|
||
if depot then
|
||
local copper = depot:countItem(CopperCoinsID)
|
||
local silver = depot:countItem(SilverCoinsID)
|
||
local gold = depot:countItem(GoldCoinsID)
|
||
return gold, silver, copper
|
||
else
|
||
return 0, 0, 0
|
||
end
|
||
end
|
||
|
||
--- Split of a total money value in copper coins into the three valid coin
|
||
-- types.
|
||
--
|
||
-- @param money - number - the total amount of money in copper coins
|
||
-- @return number - the amount of gold coins in the total amount of money
|
||
-- @return number - the amount of silver coins in the total amount of money
|
||
-- @return number - the amount of copper coins in the total amount of money
|
||
function M.MoneyToCoins(money)
|
||
local gCoins = math.floor(money / 10000)
|
||
local sCoins = math.floor((money % 10000) / 100)
|
||
local cCoins = money % 100
|
||
return gCoins, sCoins, cCoins
|
||
end
|
||
|
||
--- Check if a player has at least a certain amount of money.
|
||
--
|
||
-- @param char - CharStruct - the char who needs to have the money
|
||
-- @param money - number - the money needed at least
|
||
-- @return boolean - true in case the player has the needed amount of money
|
||
function M.CharHasMoney(char, money)
|
||
return M.CharCoinsToMoney(char) >= money
|
||
end
|
||
|
||
--- Give a exact configuration of coins to a character. This method does either
|
||
-- give all coins or none. If there is a problem while creating the items the
|
||
-- coins are removed again.
|
||
--
|
||
-- @param char - CharStruct - the char that shall receive the coins
|
||
-- @param gCoins - number - the amount of gold coins the char shall receive
|
||
-- @param sCoins - number - the amount of silver coins the char shall receive
|
||
-- @param cCoins - number - the amount of copper coins the char shall receive
|
||
-- @return boolean - true in case all items were created properly
|
||
function M.GiveCoinsToChar(char, gCoins, sCoins, cCoins)
|
||
if (gCoins > 0) then
|
||
local notCreated = char:createItem(GoldCoinsID, gCoins, 333, nil)
|
||
if (notCreated > 0) then
|
||
char:eraseItem(GoldCoinsID, gCoins - notCreated)
|
||
return false
|
||
end
|
||
end
|
||
|
||
if (sCoins > 0) then
|
||
local notCreated = char:createItem(SilverCoinsID, sCoins, 333, nil)
|
||
if (notCreated > 0) then
|
||
char:eraseItem(SilverCoinsID, sCoins - notCreated)
|
||
if (gCoins > 0) then
|
||
char:eraseItem(GoldCoinsID, gCoins)
|
||
end
|
||
return false
|
||
end
|
||
end
|
||
|
||
if (cCoins > 0) then
|
||
local notCreated = char:createItem(CopperCoinsID, cCoins, 333, nil)
|
||
if (notCreated > 0) then
|
||
char:eraseItem(CopperCoinsID, cCoins - notCreated)
|
||
if (sCoins > 0) then
|
||
char:eraseItem(SilverCoinsID, sCoins)
|
||
end
|
||
|
||
if (gCoins > 0) then
|
||
char:eraseItem(GoldCoinsID, gCoins)
|
||
end
|
||
return false
|
||
end
|
||
end
|
||
|
||
return true
|
||
end
|
||
|
||
--- Give some money to a character. This function tries to give money to the
|
||
-- character with the least amount of coin items as possible. This method gives
|
||
-- either everything or nothing. In case even one item can't be created no item
|
||
-- is given to the char.
|
||
--
|
||
-- @param char - CharStruct - the character that is supposed to receive the
|
||
-- money
|
||
-- @param money - number - the money the char is suposed to receive
|
||
-- @return boolean - true in case all items were created properly
|
||
function M.GiveMoneyToChar(char, money)
|
||
local gCoins, sCoins, cCoins = M.MoneyToCoins(money)
|
||
return M.GiveCoinsToChar(char, gCoins, sCoins, cCoins)
|
||
end
|
||
|
||
--- Give a exact configuration of coins to a position. This will create the
|
||
-- coin items on the tile at the specified location.
|
||
--
|
||
-- @param pos - PositionStruct - the target position for the coins
|
||
-- @param gCoins - number - the amount of gold coins to be created at pos
|
||
-- @param sCoins - number - the amount of silver coins to be created at pos
|
||
-- @param cCoins - number - the amount of copper coins to be created at pos
|
||
function M.GiveCoinsToPosition(pos, gCoins, sCoins, cCoins)
|
||
local maxStack = 1000
|
||
local noData = {}
|
||
|
||
while (cCoins > maxStack) do
|
||
world:createItemFromId(CopperCoinsID, maxStack, pos, true, 333, noData)
|
||
cCoins = cCoins - maxStack
|
||
end
|
||
if (cCoins > 0) then
|
||
world:createItemFromId(CopperCoinsID, cCoins, pos, true, 333, noData)
|
||
end
|
||
|
||
while (sCoins > maxStack) do
|
||
world:createItemFromId(SilverCoinsID, maxStack, pos, true, 333, noData)
|
||
sCoins = sCoins - maxStack
|
||
end
|
||
if (sCoins > 0) then
|
||
world:createItemFromId(SilverCoinsID, sCoins, pos, true, 333, noData)
|
||
end
|
||
|
||
while (gCoins > maxStack) do
|
||
world:createItemFromId(GoldCoinsID, maxStack, pos, true, 333, noData)
|
||
gCoins = gCoins - maxStack
|
||
end
|
||
if (gCoins > 0) then
|
||
world:createItemFromId(GoldCoinsID, gCoins, pos, true, 333, noData)
|
||
end
|
||
end
|
||
|
||
--- Give a amount of money to a specified position. This will create the money
|
||
-- with the least amount of coin items as possible on the target location.
|
||
--
|
||
-- @param pos - PositionStruct - the position that shall receive the money
|
||
-- @param money - number - the amount of money that shall be created on the position
|
||
function M.GiveMoneyToPosition(pos, money)
|
||
local gCoins, sCoins, cCoins = M.MoneyToCoins(money)
|
||
return M.GiveCoinsToPosition(pos, gCoins, sCoins, cCoins)
|
||
end
|
||
|
||
--- Take some coins from a character. This function only does anything in case
|
||
-- the player has the required amount of coins.
|
||
--
|
||
-- @param char - CharStruct - the char the coins are taken from
|
||
-- @param gCoins - number - the amount of gold coins taken
|
||
-- @param sCoins - number - the amount of silver coins taken
|
||
-- @param cCoins - number - the amount of copper coins taken
|
||
-- @note This method is able to give coins to the player in case the amount
|
||
-- of coins is lesser then 0.
|
||
function M.TakeCoinsFromChar(char, gCoins, sCoins, cCoins)
|
||
local charGold, charSilver, charCopper = M.CharCoins(char)
|
||
|
||
if (gCoins > charGold or sCoins > charSilver or cCoins > charCopper) then
|
||
return
|
||
end
|
||
|
||
if (gCoins > 0) then
|
||
char:eraseItem(GoldCoinsID, gCoins)
|
||
end
|
||
|
||
if (sCoins > 0) then
|
||
char:eraseItem(SilverCoinsID, sCoins)
|
||
end
|
||
|
||
if (cCoins > 0) then
|
||
char:eraseItem(CopperCoinsID, cCoins)
|
||
end
|
||
|
||
if (gCoins < 0 or sCoins < 0 or cCoins < 0) then
|
||
M.GiveCoinsToChar(char, math.min(0, gCoins) * (-1),
|
||
math.min(0, sCoins) * (-1), math.min(0, cCoins) * (-1))
|
||
end
|
||
end
|
||
|
||
--- Take some coins from a character's depot. This function only does
|
||
-- something in case the depot has the required amount of coins.
|
||
--
|
||
-- @param char - CharStruct - the char the coins are taken from
|
||
-- @param gCoins - number - the amount of gold coins taken
|
||
-- @param sCoins - number - the amount of silver coins taken
|
||
-- @param cCoins - number - the amount of copper coins taken
|
||
-- @param depotId - number - the ID of the corresponding depot
|
||
function M.TakeCoinsFromDepot(char, gCoins, sCoins, cCoins, depotId)
|
||
local charGold, charSilver, charCopper = M.DepotCoins(char,depotId)
|
||
|
||
local depot = char:getDepot(depotId)
|
||
if not depot then
|
||
return
|
||
end
|
||
|
||
if (gCoins > charGold or sCoins > charSilver or cCoins > charCopper) then
|
||
return
|
||
end
|
||
|
||
if (gCoins > 0) then
|
||
depot:eraseItem(GoldCoinsID, gCoins)
|
||
end
|
||
|
||
if (sCoins > 0) then
|
||
depot:eraseItem(SilverCoinsID, sCoins)
|
||
end
|
||
|
||
if (cCoins > 0) then
|
||
depot:eraseItem(CopperCoinsID, cCoins)
|
||
end
|
||
|
||
if (gCoins < 0 or sCoins < 0 or cCoins < 0) then
|
||
M.GiveCoinsToChar(char, math.min(0, gCoins) * (-1),
|
||
math.min(0, sCoins) * (-1), math.min(0, cCoins) * (-1))
|
||
end
|
||
end
|
||
|
||
--- This method takes a certain amount of money from the player. It tries to
|
||
-- take the least amount of coins possible. The method takes nothing in case
|
||
-- the player does not have enough money. Check this before calling this
|
||
-- method.
|
||
--
|
||
-- @param char - CharStruct - the char the money is taken from
|
||
-- @param money - number - the amount of money taken from the char
|
||
function M.TakeMoneyFromChar(char, money)
|
||
if not M.CharHasMoney(char, money) then
|
||
return
|
||
end
|
||
|
||
local MissGold, MissSilver, MissCopper = M.MoneyToCoins(money)
|
||
local _, charSilver, charCopper = M.CharCoins(char)
|
||
|
||
local GoldInCopper = math.floor(charCopper / 10000)
|
||
GoldInCopper = math.min(MissGold, GoldInCopper)
|
||
local PayCopper = GoldInCopper * 10000;
|
||
MissGold = MissGold - GoldInCopper
|
||
charCopper = charCopper - PayCopper
|
||
|
||
GoldInCopper = math.floor(charCopper / 100)
|
||
local GoldInSilver = 100 - GoldInCopper
|
||
local PaySilver = 0
|
||
|
||
if ((MissGold > 0) and (GoldInCopper > 0) and
|
||
(charSilver >= GoldInSilver)) then
|
||
PayCopper = PayCopper + 100 * GoldInCopper
|
||
PaySilver = PaySilver + GoldInSilver
|
||
MissGold = MissGold - 1
|
||
charCopper = charCopper - 100 * GoldInCopper
|
||
charSilver = charSilver - GoldInSilver
|
||
end
|
||
|
||
local SilverInCopper = math.floor(charCopper / 100)
|
||
SilverInCopper = math.min(MissSilver, SilverInCopper)
|
||
PayCopper = PayCopper + SilverInCopper * 100
|
||
MissSilver = MissSilver - SilverInCopper
|
||
charCopper = charCopper - SilverInCopper * 100
|
||
|
||
if (charCopper >= MissCopper) then
|
||
PayCopper = PayCopper + MissCopper
|
||
else
|
||
MissSilver = MissSilver + 1
|
||
PayCopper = PayCopper + MissCopper - 100
|
||
end
|
||
|
||
GoldInSilver = math.floor(charSilver / 100)
|
||
GoldInSilver = math.min(MissGold, GoldInSilver)
|
||
PaySilver = PaySilver + GoldInSilver * 100
|
||
MissGold = MissGold - GoldInSilver
|
||
charSilver = charSilver - GoldInSilver * 100
|
||
|
||
local PayGold
|
||
|
||
if (charSilver >= MissSilver) then
|
||
PayGold = MissGold
|
||
PaySilver = PaySilver + MissSilver
|
||
else
|
||
PayGold = MissGold + 1
|
||
PaySilver = PaySilver + MissSilver - 100
|
||
end
|
||
|
||
M.TakeCoinsFromChar(char, PayGold, PaySilver, PayCopper)
|
||
end
|
||
|
||
--- This method takes a certain amount of money from the depot of a player.
|
||
-- It tries to take the least amount of coins possible. The method takes
|
||
-- nothing in case the depot does not have enougth money. Check this
|
||
-- before calling this method.
|
||
--
|
||
-- @param char - CharStruct - the char the money is taken from
|
||
-- @param money - number - the amount of money taken from the char
|
||
-- @param depotId - number - the ID of the depot to take the money from
|
||
function M.TakeMoneyFromDepot(char, money, depotId)
|
||
|
||
if M.DepotCoinsToMoney(char, depotId)<money then
|
||
return
|
||
end
|
||
|
||
local PayGold
|
||
local PaySilver = 0
|
||
local PayCopper
|
||
local MissGold, MissSilver, MissCopper = M.MoneyToCoins(money)
|
||
local _, charSilver, charCopper = M.DepotCoins(char,depotId)
|
||
|
||
local GoldInCopper = math.floor(charCopper / 10000)
|
||
GoldInCopper = math.min(MissGold, GoldInCopper)
|
||
PayCopper = GoldInCopper * 10000
|
||
MissGold = MissGold - GoldInCopper
|
||
charCopper = charCopper - PayCopper
|
||
|
||
GoldInCopper = math.floor(charCopper / 100)
|
||
local GoldInSilver = 100 - GoldInCopper
|
||
if ((MissGold > 0) and (GoldInCopper > 0) and
|
||
(charSilver >= GoldInSilver)) then
|
||
PayCopper = PayCopper + 100 * GoldInCopper
|
||
PaySilver = PaySilver + GoldInSilver
|
||
MissGold = MissGold - 1
|
||
charCopper = charCopper - 100 * GoldInCopper
|
||
charSilver = charSilver - GoldInSilver
|
||
end
|
||
|
||
local SilverInCopper = math.floor(charCopper / 100)
|
||
SilverInCopper = math.min(MissSilver, SilverInCopper)
|
||
PayCopper = PayCopper + SilverInCopper * 100
|
||
MissSilver = MissSilver - SilverInCopper
|
||
charCopper = charCopper - SilverInCopper * 100
|
||
|
||
if (charCopper >= MissCopper) then
|
||
PayCopper = PayCopper + MissCopper
|
||
else
|
||
MissSilver = MissSilver + 1
|
||
PayCopper = PayCopper + MissCopper - 100
|
||
end
|
||
|
||
GoldInSilver = math.floor(charSilver / 100)
|
||
GoldInSilver = math.min(MissGold, GoldInSilver)
|
||
PaySilver = PaySilver + GoldInSilver * 100
|
||
MissGold = MissGold - GoldInSilver
|
||
charSilver = charSilver - GoldInSilver * 100
|
||
|
||
if (charSilver >= MissSilver) then
|
||
PayGold = MissGold
|
||
PaySilver = PaySilver + MissSilver
|
||
else
|
||
PayGold = MissGold + 1
|
||
PaySilver = PaySilver + MissSilver - 100
|
||
end
|
||
|
||
M.TakeCoinsFromDepot(char, PayGold, PaySilver, PayCopper,depotId)
|
||
end
|
||
|
||
function M.IsCurrency(itemId)
|
||
return itemId == CopperCoinsID or itemId == SilverCoinsID or itemId == GoldCoinsID
|
||
end
|
||
|
||
--- This method returns a german and an english string, based on the money amount.
|
||
-- @param money - number - the amount of money to be converted
|
||
function M.MoneyToString(money)
|
||
local gp, sp, cp = M.MoneyToCoins(money) --converting to gp, sp and cp
|
||
|
||
local estring = " "
|
||
local gstring = " "
|
||
|
||
if gp ~= 0 then -- at least one gold coin
|
||
estring = estring..gp.." gold coin"
|
||
gstring = gstring..gp.." Goldst<73>ck"
|
||
if gp > 1 then
|
||
estring = estring.."s"
|
||
gstring = gstring.."e"
|
||
end
|
||
if sp ~= 0 and cp ~= 0 then
|
||
estring = estring..", "
|
||
gstring = gstring..", "
|
||
elseif sp ~= 0 or cp ~= 0 then
|
||
estring = estring.." and "
|
||
gstring = gstring.." und "
|
||
end
|
||
end
|
||
|
||
if sp ~= 0 then -- at least one silver coin
|
||
estring = estring..sp.." silver coin"
|
||
gstring = gstring..sp.." Silberst<73>ck"
|
||
if sp > 1 then
|
||
estring = estring.."s"
|
||
gstring = gstring.."e"
|
||
end
|
||
if cp ~= 0 then
|
||
estring = estring.." and "
|
||
gstring = gstring.." und "
|
||
end
|
||
end
|
||
|
||
if cp ~= 0 then -- at least one copper coin
|
||
estring = estring..cp.." copper coin"
|
||
gstring = gstring..cp.." Kupferst<73>ck"
|
||
if cp > 1 then
|
||
estring = estring.."s"
|
||
gstring = gstring.."e"
|
||
end
|
||
end
|
||
|
||
return gstring, estring
|
||
end
|
||
|
||
return M
|