Skip to content

Commit

Permalink
Possibility of defining currencies (#3699)
Browse files Browse the repository at this point in the history
  • Loading branch information
MillhioreBT authored Dec 1, 2021
1 parent ffe69a5 commit 40206c5
Show file tree
Hide file tree
Showing 14 changed files with 152 additions and 108 deletions.
3 changes: 0 additions & 3 deletions data/actions/actions.xml
Original file line number Diff line number Diff line change
Expand Up @@ -154,9 +154,6 @@
<action itemid="2095" script="other/bird_cage.lua" />
<action itemid="2099" script="other/water_pipe.lua" />
<action itemid="2114" script="other/piggy_bank.lua" />
<action itemid="2148" script="other/change_gold.lua" />
<action itemid="2152" script="other/change_gold.lua" />
<action itemid="2160" script="other/change_gold.lua" />
<action fromid="2376" toid="2404" script="other/destroy.lua" />
<action fromid="2406" toid="2415" script="other/destroy.lua" />
<action fromid="2417" toid="2419" script="other/destroy.lua" />
Expand Down
19 changes: 0 additions & 19 deletions data/actions/scripts/other/change_gold.lua

This file was deleted.

3 changes: 3 additions & 0 deletions data/items/items.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2177,6 +2177,7 @@
</item>
<item id="2148" article="a" name="gold coin">
<attribute key="weight" value="10" />
<attribute key="worth" value="1" />
</item>
<item id="2149" article="a" name="small emerald">
<attribute key="weight" value="10" />
Expand All @@ -2190,6 +2191,7 @@
</item>
<item id="2152" article="a" name="platinum coin">
<attribute key="weight" value="10" />
<attribute key="worth" value="100" />
</item>
<item id="2153" article="a" name="violet gem">
<attribute key="weight" value="30" />
Expand All @@ -2214,6 +2216,7 @@
</item>
<item id="2160" article="a" name="crystal coin">
<attribute key="weight" value="10" />
<attribute key="worth" value="10000" />
</item>
<item id="2161" article="a" name="strange talisman">
<attribute key="weight" value="290" />
Expand Down
48 changes: 14 additions & 34 deletions data/lib/core/player.lua
Original file line number Diff line number Diff line change
Expand Up @@ -171,40 +171,20 @@ function Player.canCarryMoney(self, amount)
local totalWeight = 0
local inventorySlots = 0

-- Add crystal coins to totalWeight and inventorySlots
local type_crystal = ItemType(ITEM_CRYSTAL_COIN)
local crystalCoins = math.floor(amount / 10000)
if crystalCoins > 0 then
amount = amount - (crystalCoins * 10000)
while crystalCoins > 0 do
local count = math.min(100, crystalCoins)
totalWeight = totalWeight + type_crystal:getWeight(count)
crystalCoins = crystalCoins - count
inventorySlots = inventorySlots + 1
end
end

-- Add platinum coins to totalWeight and inventorySlots
local type_platinum = ItemType(ITEM_PLATINUM_COIN)
local platinumCoins = math.floor(amount / 100)
if platinumCoins > 0 then
amount = amount - (platinumCoins * 100)
while platinumCoins > 0 do
local count = math.min(100, platinumCoins)
totalWeight = totalWeight + type_platinum:getWeight(count)
platinumCoins = platinumCoins - count
inventorySlots = inventorySlots + 1
end
end

-- Add gold coins to totalWeight and inventorySlots
local type_gold = ItemType(ITEM_GOLD_COIN)
if amount > 0 then
while amount > 0 do
local count = math.min(100, amount)
totalWeight = totalWeight + type_gold:getWeight(count)
amount = amount - count
inventorySlots = inventorySlots + 1
local currencyItems = Game.getCurrencyItems()
for index = #currencyItems, 1, -1 do
local currency = currencyItems[index]
-- Add currency coins to totalWeight and inventorySlots
local worth = currency:getWorth()
local currencyCoins = math.floor(amount / worth)
if currencyCoins > 0 then
amount = amount - (currencyCoins * worth)
while currencyCoins > 0 do
local count = math.min(100, currencyCoins)
totalWeight = totalWeight + currency:getWeight(count)
currencyCoins = currencyCoins - count
inventorySlots = inventorySlots + 1
end
end
end

Expand Down
17 changes: 11 additions & 6 deletions data/npc/lib/npc.lua
Original file line number Diff line number Diff line change
Expand Up @@ -131,10 +131,15 @@ function getMoneyCount(string)
end

function getMoneyWeight(money)
local gold = money
local crystal = math.floor(gold / 10000)
gold = gold - crystal * 10000
local platinum = math.floor(gold / 100)
gold = gold - platinum * 100
return (ItemType(ITEM_CRYSTAL_COIN):getWeight() * crystal) + (ItemType(ITEM_PLATINUM_COIN):getWeight() * platinum) + (ItemType(ITEM_GOLD_COIN):getWeight() * gold)
local weight, currencyItems = 0, Game.getCurrencyItems()
for index = #currencyItems, 1, -1 do
local currency = currencyItems[index]
local worth = currency:getWorth()
local currencyCoins = math.floor(money / worth)
if currencyCoins > 0 then
money = money - (currencyCoins * worth)
weight = weight + currency:getWeight(currencyCoins)
end
end
return weight
end
27 changes: 27 additions & 0 deletions data/scripts/actions/others/change_gold.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
local config = {}

local changeGold = Action()

function changeGold.onUse(player, item, fromPosition, target, toPosition, isHotkey)
local coin = config[item:getId()]
if coin.changeTo and item.type == 100 then
item:remove()
player:addItem(coin.changeTo, 1)
elseif coin.changeBack then
item:remove(1)
player:addItem(coin.changeBack, 100)
else
return false
end
return true
end

local currencyItems = Game.getCurrencyItems()
for index, currency in pairs(currencyItems) do
local back, to = currencyItems[index-1], currencyItems[index+1]
local currencyId = currency:getId()
config[currencyId] = { changeBack = back and back:getId(), changeTo = to and to:getId() }
changeGold:id(currencyId)
end

changeGold:register()
13 changes: 8 additions & 5 deletions data/scripts/actions/tools/gold_converter.lua
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
local config = {
[ITEM_GOLD_COIN] = {changeTo = ITEM_PLATINUM_COIN},
[ITEM_PLATINUM_COIN] = {changeBack = ITEM_GOLD_COIN, changeTo = ITEM_CRYSTAL_COIN},
[ITEM_CRYSTAL_COIN] = {changeBack = ITEM_PLATINUM_COIN}
}
local config = {}

local goldConverter = Action()

Expand Down Expand Up @@ -32,5 +28,12 @@ function goldConverter.onUse(player, item, fromPosition, target, toPosition, isH
return true
end

local currencyItems = Game.getCurrencyItems()
for index, currency in pairs(currencyItems) do
local back, to = currencyItems[index-1], currencyItems[index+1]
local currencyId = currency:getId()
config[currencyId] = { changeBack = back and back:getId(), changeTo = to and to:getId() }
end

goldConverter:id(26378)
goldConverter:register()
41 changes: 14 additions & 27 deletions src/game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1567,39 +1567,26 @@ void Game::addMoney(Cylinder* cylinder, uint64_t money, uint32_t flags /*= 0*/)
return;
}

uint32_t crystalCoins = money / 10000;
money -= crystalCoins * 10000;
while (crystalCoins > 0) {
const uint16_t count = std::min<uint32_t>(100, crystalCoins);
for (const auto& it : Item::items.currencyItems) {
const uint64_t worth = it.first;

Item* remaindItem = Item::CreateItem(ITEM_CRYSTAL_COIN, count);

ReturnValue ret = internalAddItem(cylinder, remaindItem, INDEX_WHEREEVER, flags);
if (ret != RETURNVALUE_NOERROR) {
internalAddItem(cylinder->getTile(), remaindItem, INDEX_WHEREEVER, FLAG_NOLIMIT);
uint32_t currencyCoins = money / worth;
if (currencyCoins <= 0) {
continue;
}

crystalCoins -= count;
}
money -= currencyCoins * worth;
while (currencyCoins > 0) {
const uint16_t count = std::min<uint32_t>(100, currencyCoins);

uint16_t platinumCoins = money / 100;
if (platinumCoins != 0) {
Item* remaindItem = Item::CreateItem(ITEM_PLATINUM_COIN, platinumCoins);
Item* remaindItem = Item::CreateItem(it.second, count);

ReturnValue ret = internalAddItem(cylinder, remaindItem, INDEX_WHEREEVER, flags);
if (ret != RETURNVALUE_NOERROR) {
internalAddItem(cylinder->getTile(), remaindItem, INDEX_WHEREEVER, FLAG_NOLIMIT);
}

money -= platinumCoins * 100;
}

if (money != 0) {
Item* remaindItem = Item::CreateItem(ITEM_GOLD_COIN, money);
ReturnValue ret = internalAddItem(cylinder, remaindItem, INDEX_WHEREEVER, flags);
if (ret != RETURNVALUE_NOERROR) {
internalAddItem(cylinder->getTile(), remaindItem, INDEX_WHEREEVER, FLAG_NOLIMIT);
}

ReturnValue ret = internalAddItem(cylinder, remaindItem, INDEX_WHEREEVER, flags);
if (ret != RETURNVALUE_NOERROR) {
internalAddItem(cylinder->getTile(), remaindItem, INDEX_WHEREEVER, FLAG_NOLIMIT);
currencyCoins -= count;
}
}
}
Expand Down
14 changes: 1 addition & 13 deletions src/item.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1658,19 +1658,7 @@ bool Item::canDecay() const

uint32_t Item::getWorth() const
{
switch (id) {
case ITEM_GOLD_COIN:
return count;

case ITEM_PLATINUM_COIN:
return count * 100;

case ITEM_CRYSTAL_COIN:
return count * 10000;

default:
return 0;
}
return items[id].worth * count;
}

LightInfo Item::getLightInfo() const
Expand Down
13 changes: 13 additions & 0 deletions src/items.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ const std::unordered_map<std::string, ItemParseAttributes_t> ItemParseAttributes
{"blocking", ITEM_PARSE_BLOCKING},
{"allowdistread", ITEM_PARSE_ALLOWDISTREAD},
{"storeitem", ITEM_PARSE_STOREITEM},
{"worth", ITEM_PARSE_WORTH},
};

const std::unordered_map<std::string, ItemTypes_t> ItemTypesMap = {
Expand Down Expand Up @@ -226,6 +227,7 @@ void Items::clear()
items.clear();
clientIdToServerIdMap.clear();
nameToItems.clear();
currencyItems.clear();
inventory.clear();
}

Expand Down Expand Up @@ -1346,6 +1348,17 @@ void Items::parseItemNode(const pugi::xml_node& itemNode, uint16_t id)
break;
}

case ITEM_PARSE_WORTH: {
uint64_t worth = pugi::cast<uint64_t>(valueAttribute.value());
if (currencyItems.find(worth) != currencyItems.end()) {
std::cout << "[Warning - Items::parseItemNode] Duplicated currency worth. Item " << id << " redefines worth " << worth << std::endl;
} else {
currencyItems.insert(CurrencyMap::value_type(worth, id));
it.worth = worth;
}
break;
}

default: {
// It should not ever get to here, only if you add a new key to the map and don't configure a case for it.
std::cout << "[Warning - Items::parseItemNode] Not configured key value: " << keyAttribute.as_string() << std::endl;
Expand Down
5 changes: 5 additions & 0 deletions src/items.h
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ enum ItemParseAttributes_t {
ITEM_PARSE_BLOCKING,
ITEM_PARSE_ALLOWDISTREAD,
ITEM_PARSE_STOREITEM,
ITEM_PARSE_WORTH,
};

struct Abilities {
Expand Down Expand Up @@ -330,6 +331,7 @@ class ItemType
uint16_t rotateTo = 0;
int32_t runeMagLevel = 0;
int32_t runeLevel = 0;
uint64_t worth = 0;

CombatType_t combatType = COMBAT_NONE;

Expand Down Expand Up @@ -396,6 +398,8 @@ class Items
using NameMap = std::unordered_map<std::string, uint16_t>;
using InventoryVector = std::vector<uint16_t>;

using CurrencyMap = std::map<uint64_t, uint16_t, std::greater<uint64_t>>;

Items();

// non-copyable
Expand Down Expand Up @@ -428,6 +432,7 @@ class Items
}

NameMap nameToItems;
CurrencyMap currencyItems;

private:
std::vector<ItemType> items;
Expand Down
Loading

0 comments on commit 40206c5

Please sign in to comment.