diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9c8ffef6c0a..e4093f4de2d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -8,7 +8,7 @@ cmake_minimum_required(VERSION 3.22 FATAL_ERROR)
# VCPKG
# cmake -DCMAKE_TOOLCHAIN_FILE=/opt/workspace/vcpkg/scripts/buildsystems/vcpkg.cmake ..
# Needed libs is in file vcpkg.json
-# Windows required libs: .\vcpkg install --triplet x64-windows asio pugixml spdlog curl jsoncpp protobuf parallel-hashmap magic-enum mio luajit libmariadb mpir abseil
+# Windows required libs: .\vcpkg install --triplet x64-windows asio pugixml spdlog curl protobuf parallel-hashmap magic-enum mio luajit libmariadb mpir abseil
if(DEFINED ENV{VCPKG_ROOT} AND NOT DEFINED CMAKE_TOOLCHAIN_FILE)
set(CMAKE_TOOLCHAIN_FILE "$ENV{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake"
CACHE STRING "")
@@ -48,11 +48,18 @@ include(LoggingHelper)
option(OPTIONS_ENABLE_CCACHE "Enable ccache" OFF)
option(OPTIONS_ENABLE_SCCACHE "Use sccache to speed up compilation process" OFF)
option(OPTIONS_ENABLE_IPO "Check and Enable interprocedural optimization (IPO/LTO)" ON)
+option(FEATURE_METRICS "Enable metrics feature" OFF)
# *****************************************************************************
# Options Code
# *****************************************************************************
+if(FEATURE_METRIC)
+ log_option_enabled("metrics")
+else ()
+ log_option_disabled("metrics")
+endif ()
+
# === CCACHE ===
if(OPTIONS_ENABLE_CCACHE)
find_program(CCACHE ccache)
diff --git a/cmake/modules/BaseConfig.cmake b/cmake/modules/BaseConfig.cmake
index 6f58a2eebdb..7e3f6404b3f 100644
--- a/cmake/modules/BaseConfig.cmake
+++ b/cmake/modules/BaseConfig.cmake
@@ -31,10 +31,11 @@ find_package(ZLIB REQUIRED)
find_package(absl CONFIG REQUIRED)
find_package(asio CONFIG REQUIRED)
find_package(eventpp CONFIG REQUIRED)
-find_package(jsoncpp CONFIG REQUIRED)
find_package(magic_enum CONFIG REQUIRED)
-find_package(opentelemetry-cpp CONFIG REQUIRED)
-find_package(prometheus-cpp CONFIG REQUIRED)
+if(FEATURE_METRICS)
+ find_package(opentelemetry-cpp CONFIG REQUIRED)
+ find_package(prometheus-cpp CONFIG REQUIRED)
+endif()
find_package(mio REQUIRED)
find_package(pugixml CONFIG REQUIRED)
find_package(spdlog REQUIRED)
diff --git a/cmake/modules/CanaryLib.cmake b/cmake/modules/CanaryLib.cmake
index 4838935f19e..a3f5410b9d8 100644
--- a/cmake/modules/CanaryLib.cmake
+++ b/cmake/modules/CanaryLib.cmake
@@ -105,17 +105,25 @@ target_link_libraries(${PROJECT_NAME}_lib
unofficial::argon2::libargon2
unofficial::libmariadb
unofficial::mariadbclient
- opentelemetry-cpp::common
- opentelemetry-cpp::metrics
- opentelemetry-cpp::api
- opentelemetry-cpp::ext
- opentelemetry-cpp::sdk
- opentelemetry-cpp::logs
- opentelemetry-cpp::ostream_metrics_exporter
- opentelemetry-cpp::prometheus_exporter
protobuf
)
+if(FEATURE_METRICS)
+ add_definitions(-DFEATURE_METRICS)
+
+ target_link_libraries(${PROJECT_NAME}_lib
+ PUBLIC
+ opentelemetry-cpp::common
+ opentelemetry-cpp::metrics
+ opentelemetry-cpp::api
+ opentelemetry-cpp::ext
+ opentelemetry-cpp::sdk
+ opentelemetry-cpp::logs
+ opentelemetry-cpp::ostream_metrics_exporter
+ opentelemetry-cpp::prometheus_exporter
+ )
+endif()
+
if(CMAKE_BUILD_TYPE MATCHES Debug)
target_link_libraries(${PROJECT_NAME}_lib PUBLIC ${ZLIB_LIBRARY_DEBUG})
else()
@@ -124,16 +132,14 @@ endif()
if (MSVC)
if(BUILD_STATIC_LIBRARY)
- target_link_libraries(${PROJECT_NAME}_lib PUBLIC jsoncpp_static)
set(VCPKG_TARGET_TRIPLET "x64-windows-static" CACHE STRING "")
else()
- target_link_libraries(${PROJECT_NAME}_lib PUBLIC jsoncpp_lib)
set(VCPKG_TARGET_TRIPLET "x64-windows" CACHE STRING "")
endif()
target_link_libraries(${PROJECT_NAME}_lib PUBLIC ${CMAKE_THREAD_LIBS_INIT} ${MYSQL_CLIENT_LIBS})
else()
- target_link_libraries(${PROJECT_NAME}_lib PUBLIC jsoncpp_static Threads::Threads)
+ target_link_libraries(${PROJECT_NAME}_lib PUBLIC Threads::Threads)
endif (MSVC)
# === OpenMP ===
diff --git a/config.lua.dist b/config.lua.dist
index a5bb3d73ca5..0507b652e29 100644
--- a/config.lua.dist
+++ b/config.lua.dist
@@ -212,6 +212,8 @@ wheelAtelierRevealGreaterCost = 6000000
familiarTime = 30
partyAutoShareExperience = true
+-- partyShareRangeMultiplier: the range of the party share experience, default 3/2 (1.5)
+partyShareRangeMultiplier = 1.5
partyShareLootBoosts = false
partyShareLootBoostsDimishingFactor = 0.7
@@ -239,6 +241,7 @@ onlyPremiumAccount = false
-- NOTE: enablePlayerPutItemInAmmoSlot = true, will enable players to put any items on ammo slot, more used in custom shopping system
-- NOTE: startStreakLevel will make a reward streak level for new players who never logged in
-- NOTE: if showLootsInBestiary is true, will cause all loots to be shown in the bestiary even if the player has not reached the required number of kills
+-- NOTE: minTownIdToBankTransfer blocks towns less than defined from receiving money transfers
stashMoving = false
depotChest = 4
autoLoot = false
@@ -257,6 +260,7 @@ storeInboxMaxLimit = 2000
enablePlayerPutItemInAmmoSlot = false
startStreakLevel = 0
showLootsInBestiary = false
+minTownIdToBankTransfer = 3
-- Teleport summon
-- Set to true will never remove the summon
diff --git a/data-otservbr-global/lib/core/storages.lua b/data-otservbr-global/lib/core/storages.lua
index 50d4d409379..87588037ac7 100644
--- a/data-otservbr-global/lib/core/storages.lua
+++ b/data-otservbr-global/lib/core/storages.lua
@@ -106,7 +106,6 @@ Storage = {
-- unused ExerciseDummyExhaust = 30029,
SamsOldBackpack = 30030,
SamsOldBackpackDoor = 30031,
- StrawberryCupcake = 30032,
ChayenneReward = 30033,
SwampDiggingTimeout = 30034,
HydraEggQuest = 30035,
@@ -125,8 +124,6 @@ Storage = {
Navigator = 30048,
DwarvenLegs = 30049,
PrinceDrazzakTime = 30050,
- LemonCupcake = 30052,
- BlueberryCupcake = 30053,
-- Reserved in Global.Storage.FamiliarSummonEvent10 = 30054
-- Reserved in Global.Storage.FamiliarSummonEvent60 = 30055
ChayenneKeyTime = 30056,
diff --git a/data-otservbr-global/npc/asnarus.lua b/data-otservbr-global/npc/asnarus.lua
index a733d90834b..3992d513e9b 100644
--- a/data-otservbr-global/npc/asnarus.lua
+++ b/data-otservbr-global/npc/asnarus.lua
@@ -56,7 +56,7 @@ npcConfig.shop = {
{ itemName = "animate dead rune", clientId = 3203, buy = 375 },
{ itemName = "arrow", clientId = 3447, buy = 2 },
{ itemName = "blue quiver", clientId = 35848, buy = 400 },
- { itemName = "bolt", clientId = 3483, buy = 4 },
+ { itemName = "bolt", clientId = 3446, buy = 4 },
{ itemName = "bow", clientId = 3350, buy = 400, sell = 100 },
{ itemName = "bowl of terror sweat", clientId = 20204, sell = 500 },
{ itemName = "broken visor", clientId = 20184, sell = 1900 },
diff --git a/data-otservbr-global/npc/hireling.lua b/data-otservbr-global/npc/hireling.lua
index 145d846bd7e..aad7785079d 100644
--- a/data-otservbr-global/npc/hireling.lua
+++ b/data-otservbr-global/npc/hireling.lua
@@ -228,7 +228,7 @@ function createHirelingType(HirelingName)
},
["distance"] = {
{ itemName = "arrow", clientId = 3447, buy = 2 },
- { itemName = "bolt", clientId = 3483, buy = 4 },
+ { itemName = "bolt", clientId = 3446, buy = 4 },
{ itemName = "bow", clientId = 3350, buy = 400, sell = 100 },
{ itemName = "crossbow", clientId = 3349, buy = 500, sell = 120 },
{ itemName = "crystalline arrow", clientId = 15793, buy = 450 },
diff --git a/data-otservbr-global/scripts/actions/other/cup_cakes.lua b/data-otservbr-global/scripts/actions/other/cup_cakes.lua
deleted file mode 100644
index a9d94dbaacd..00000000000
--- a/data-otservbr-global/scripts/actions/other/cup_cakes.lua
+++ /dev/null
@@ -1,51 +0,0 @@
-local data = {
- [28484] = {
- Type = "mana",
- ExhaustStor = Storage.BlueberryCupcake,
- timestamp = 10,
- },
- [28485] = {
- Type = "health",
- ExhaustStor = Storage.StrawberryCupcake,
- timestamp = 10,
- },
- [28486] = {
- Type = "skill",
- ExhaustStor = Storage.LemonCupcake,
- timestamp = 10,
- },
-}
-
-local lemon = Condition(CONDITION_ATTRIBUTES)
-lemon:setParameter(CONDITION_PARAM_TICKS, 60 * 60 * 1000)
-lemon:setParameter(CONDITION_PARAM_SKILL_DISTANCE, 10)
-
-local cupCakes = Action()
-
-function cupCakes.onUse(player, item, fromPos, itemEx, toPos)
- local foundItem = data[item.itemid]
- if not foundItem then
- return
- end
- if (player:getStorageValue(foundItem.ExhaustStor)) < os.time() then
- if foundItem.Type == "mana" then
- player:addMana(player:getMaxMana())
- player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Your mana has been refilled.")
- elseif foundItem.Type == "health" then
- player:addHealth(player:getMaxHealth())
- player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Your health has been refilled.")
- elseif foundItem.Type == "skill" then
- player:addCondition(lemon)
- player:sendTextMessage(MESSAGE_FAILURE, "You feel more focused.")
- end
- player:say("Mmmm.", TALKTYPE_MONSTER_SAY)
- item:remove(1)
- player:setStorageValue(foundItem.ExhaustStor, os.time() + (foundItem.timestamp * 60))
- else
- player:sendTextMessage(MESSAGE_FAILURE, "You need to wait before using it again.")
- end
- return true
-end
-
-cupCakes:id(28484, 28485, 28486)
-cupCakes:register()
diff --git a/data/items/items.xml b/data/items/items.xml
index b1a1c6b003f..765c6e9db51 100644
--- a/data/items/items.xml
+++ b/data/items/items.xml
@@ -34797,7 +34797,7 @@
-
+
diff --git a/data/modules/scripts/daily_reward/daily_reward.lua b/data/modules/scripts/daily_reward/daily_reward.lua
index 815a7e2611c..1f0e805704c 100644
--- a/data/modules/scripts/daily_reward/daily_reward.lua
+++ b/data/modules/scripts/daily_reward/daily_reward.lua
@@ -462,14 +462,12 @@ function Player.selectDailyReward(self, msg)
local description = ""
for k, v in ipairs(items) do
if dailyTable.itemCharges then
- for i = 1, rewardCount do
- local inboxItem = inbox:addItem(v.itemId, dailyTable.itemCharges) -- adding charges for each item
- if inboxItem then
- inboxItem:setAttribute(ITEM_ATTRIBUTE_STORE, systemTime())
- end
+ local inboxItem = inbox:addItem(v.itemId, dailyTable.itemCharges) -- adding charges for each item
+ if inboxItem then
+ inboxItem:setAttribute(ITEM_ATTRIBUTE_STORE, systemTime())
end
else
- local inboxItem = inbox:addItem(v.itemId, rewardCount) -- adding single item w/o charges
+ local inboxItem = inbox:addItem(v.itemId, v.count) -- adding single item w/o charges
if inboxItem then
inboxItem:setAttribute(ITEM_ATTRIBUTE_STORE, systemTime())
end
diff --git a/data/modules/scripts/gamestore/init.lua b/data/modules/scripts/gamestore/init.lua
index a927715cd93..6146f562307 100644
--- a/data/modules/scripts/gamestore/init.lua
+++ b/data/modules/scripts/gamestore/init.lua
@@ -402,7 +402,7 @@ function parseBuyStoreOffer(playerId, msg)
-- All guarding conditions under which the offer should not be processed must be included here
if
- (table.contains(GameStore.OfferTypes, offer.type) == false) -- we've got an invalid offer type
+ not table.contains(GameStore.OfferTypes, offer.type) -- we've got an invalid offer type
or not player
or (player:getVocation():getId() == 0) and (not GameStore.haveOfferRook(id)) -- we don't have such offer
or not offer
@@ -620,7 +620,7 @@ end
function Player.canBuyOffer(self, offer)
local playerId = self:getId()
local disabled, disabledReason = 0, ""
- if offer.disabled == true or not offer.type then
+ if offer.disabled or not offer.type then
disabled = 1
end
@@ -692,8 +692,7 @@ function Player.canBuyOffer(self, offer)
disabledReason = "The offer is fake."
end
elseif offer.type == GameStore.OfferTypes.OFFER_TYPE_MOUNT then
- local hasMount = self:hasMount(offer.id)
- if hasMount == true then
+ if self:hasMount(offer.id) then
disabled = 1
disabledReason = "You already have this mount."
end
@@ -723,12 +722,11 @@ function Player.canBuyOffer(self, offer)
disabledReason = "You already have 3 slots released."
end
elseif offer.type == GameStore.OfferTypes.OFFER_TYPE_EXPBOOST then
- local remainingBoost = self:getExpBoostStamina()
if self:getStorageValue(GameStore.Storages.expBoostCount) == 6 then
disabled = 1
disabledReason = "You can't buy XP Boost for today."
end
- if remainingBoost > 0 then
+ if self:getExpBoostStamina() > 0 then
disabled = 1
disabledReason = "You already have an active XP boost."
end
@@ -786,9 +784,9 @@ function Player.canReceiveStoreItems(self, offerId, offerCount)
local inboxItems = inbox:getItems(true)
local slotsOccupied = #inboxItems
local maxCapacity = inbox:getMaxCapacity()
- local slotsAvailable = maxCapacity - slotsOccupied
if slotsOccupied + slotsNeeded > maxCapacity then
+ local slotsAvailable = maxCapacity - slotsOccupied
return false, string.format("Not enough free slots in your store inbox. You need %d more slot(s). Currently occupied: %d/%d", slotsNeeded - slotsAvailable, slotsOccupied, maxCapacity)
end
@@ -1104,14 +1102,16 @@ function sendStoreTransactionHistory(playerId, page, entriesPerPage)
if not player then
return false
end
- local oldProtocol = player:getClient().version < 1200
- local totalEntries = GameStore.retrieveHistoryTotalPages(player:getAccountId())
- local totalPages = math.ceil(totalEntries / entriesPerPage)
+
local entries = GameStore.retrieveHistoryEntries(player:getAccountId(), page, entriesPerPage) -- this makes everything easy!
if #entries == 0 then
return addPlayerEvent(sendStoreError, 250, playerId, GameStore.StoreErrors.STORE_ERROR_HISTORY, "You don't have any entries yet.")
end
+ local oldProtocol = player:getClient().version < 1200
+ local totalEntries = GameStore.retrieveHistoryTotalPages(player:getAccountId())
+ local totalPages = math.ceil(totalEntries / entriesPerPage)
+
local msg = NetworkMessage()
msg:addByte(GameStore.SendingPackets.S_OpenTransactionHistory)
msg:addU32(totalPages > 0 and page - 1 or 0x0) -- current page
@@ -1165,10 +1165,8 @@ function sendStoreError(playerId, errorType, message)
local msg = NetworkMessage()
msg:addByte(GameStore.SendingPackets.S_StoreError)
-
msg:addByte(errorType)
msg:addString(message, "sendStoreError - message")
-
msg:sendToPlayer(player)
end
@@ -1183,7 +1181,7 @@ function sendStoreBalanceUpdating(playerId, updating)
msg:addByte(0x00)
msg:sendToPlayer(player)
- if updating == true then
+ if updating then
sendUpdatedStoreBalances(playerId)
end
end
@@ -1194,7 +1192,6 @@ function sendUpdatedStoreBalances(playerId)
return false
end
- local oldProtocol = player:getClient().version < 1200
local msg = NetworkMessage()
msg:addByte(GameStore.SendingPackets.S_CoinBalanceUpdating)
msg:addByte(0x01)
@@ -1205,6 +1202,8 @@ function sendUpdatedStoreBalances(playerId)
-- Send total of coins (transferable and normal coin)
msg:addU32(player:getTibiaCoins())
msg:addU32(player:getTransferableCoins()) -- How many are Transferable
+
+ local oldProtocol = player:getClient().version < 1200
if not oldProtocol then
-- How many are reserved for a Character Auction
-- We currently do not have this system implemented, so we will send 0
@@ -1346,7 +1345,7 @@ end
GameStore.retrieveHistoryTotalPages = function(accountId)
local resultId = db.storeQuery("SELECT count(id) as total FROM store_history WHERE account_id = " .. accountId)
- if resultId == false then
+ if not resultId then
return 0
end
@@ -1360,7 +1359,7 @@ GameStore.retrieveHistoryEntries = function(accountId, currentPage, entriesPerPa
local offset = currentPage > 1 and entriesPerPage * (currentPage - 1) or 0
local resultId = db.storeQuery("SELECT * FROM `store_history` WHERE `account_id` = " .. accountId .. " ORDER BY `time` DESC LIMIT " .. offset .. ", " .. entriesPerPage .. ";")
- if resultId ~= false then
+ if resultId then
repeat
local entry = {
mode = Result.getNumber(resultId, "mode"),
@@ -1602,7 +1601,7 @@ function GameStore.processStackablePurchase(player, offerId, offerCount, offerNa
local countToAdd = math.min(remainingCount, stackSize)
local inboxItem = inbox:addItem(offerId, countToAdd)
if inboxItem then
- if movable ~= true then
+ if not movable then
inboxItem:setAttribute(ITEM_ATTRIBUTE_STORE, systemTime())
end
else
@@ -1631,21 +1630,32 @@ function GameStore.processHouseRelatedPurchase(player, offer)
local inbox = player:getStoreInbox()
if inbox then
for _, itemId in ipairs(itemIds) do
- for i = 1, offer.count do
+ if isCaskItem(itemId) then
local decoKit = inbox:addItem(ITEM_DECORATION_KIT, 1)
if decoKit then
decoKit:setAttribute(ITEM_ATTRIBUTE_DESCRIPTION, "You bought this item in the Store.\nUnwrap it in your own house to create a <" .. ItemType(itemId):getName() .. ">.")
decoKit:setCustomAttribute("unWrapId", itemId)
- if isCaskItem(itemId) then
- decoKit:setAttribute(ITEM_ATTRIBUTE_DATE, offer.count)
- end
+ decoKit:setAttribute(ITEM_ATTRIBUTE_DATE, offer.count)
- if offer.movable ~= true then
+ if not offer.movable then
decoKit:setAttribute(ITEM_ATTRIBUTE_STORE, systemTime())
end
end
+ player:sendUpdateContainer(inbox)
+ else
+ for i = 1, offer.count do
+ local decoKit = inbox:addItem(ITEM_DECORATION_KIT, 1)
+ if decoKit then
+ decoKit:setAttribute(ITEM_ATTRIBUTE_DESCRIPTION, "You bought this item in the Store.\nUnwrap it in your own house to create a <" .. ItemType(itemId):getName() .. ">.")
+ decoKit:setCustomAttribute("unWrapId", itemId)
+
+ if not offer.movable then
+ decoKit:setAttribute(ITEM_ATTRIBUTE_STORE, systemTime())
+ end
+ end
+ player:sendUpdateContainer(inbox)
+ end
end
- player:sendUpdateContainer(inbox)
end
end
end
@@ -1689,8 +1699,6 @@ function GameStore.processMountPurchase(player, offerId)
end
function GameStore.processNameChangePurchase(player, offer, productType, newName)
- local playerId = player:getId()
-
if productType == GameStore.ClientOfferTypes.CLIENT_STORE_OFFER_NAMECHANGE then
local tile = Tile(player:getPosition())
if tile then
@@ -1720,11 +1728,11 @@ function GameStore.processNameChangePurchase(player, offer, productType, newName
else
message = "Your character has been renamed successfully."
end
- addPlayerEvent(sendStorePurchaseSuccessful, 500, playerId, message)
+ addPlayerEvent(sendStorePurchaseSuccessful, 500, player:getId(), message)
player:changeName(newName)
else
- return addPlayerEvent(sendRequestPurchaseData, 250, playerId, offer.id, GameStore.ClientOfferTypes.CLIENT_STORE_OFFER_NAMECHANGE)
+ return addPlayerEvent(sendRequestPurchaseData, 250, player:getId(), offer.id, GameStore.ClientOfferTypes.CLIENT_STORE_OFFER_NAMECHANGE)
end
end
@@ -1780,9 +1788,6 @@ function GameStore.processTempleTeleportPurchase(player)
end
function GameStore.processHirelingPurchase(player, offer, productType, hirelingName, chosenSex)
- local playerId = player:getId()
- local offerId = offer.id
-
if player:getClient().version < 1200 then
return error({ code = 1, message = "You cannot buy hirelings on client 10, please relog on client 12 and try again." })
end
@@ -1804,7 +1809,7 @@ function GameStore.processHirelingPurchase(player, offer, productType, hirelingN
player:makeCoinTransaction(offer, hirelingName)
local message = "You have successfully bought " .. hirelingName
- return addPlayerEvent(sendStorePurchaseSuccessful, 650, playerId, message)
+ return addPlayerEvent(sendStorePurchaseSuccessful, 650, player:getId(), message)
-- If not, we ask him to do!
else
if player:getHirelingsCount() >= 10 then
@@ -1812,14 +1817,50 @@ function GameStore.processHirelingPurchase(player, offer, productType, hirelingN
end
-- TODO: Use the correct dialog (byte 0xDB) on client 1205+
-- for compatibility, request name using the change name dialog
- return addPlayerEvent(sendRequestPurchaseData, 250, playerId, offerId, GameStore.ClientOfferTypes.CLIENT_STORE_OFFER_HIRELING)
+ return addPlayerEvent(sendRequestPurchaseData, 250, player:getId(), offer.id, GameStore.ClientOfferTypes.CLIENT_STORE_OFFER_HIRELING)
end
end
-function GameStore.processHirelingChangeNamePurchase(player, offer, productType, newHirelingName)
- local playerId = player:getId()
- local offerId = offer.id
+-- Hireling Helpers
+local function HandleHirelingNameChange(playerId, offer, newHirelingName)
+ local player = Player(playerId)
+ if not player then
+ return
+ end
+
+ local functionCallback = function(playerIdInFunction, data, hireling)
+ local playerInFunction = Player(playerIdInFunction)
+ if not playerInFunction then
+ return
+ end
+
+ if not hireling then
+ return playerInFunction:showInfoModal("Error", "Your must select a hireling.")
+ end
+ if hireling.active > 0 then
+ return playerInFunction:showInfoModal("Error", "Your hireling must be inside his/her lamp.")
+ end
+
+ local oldName = hireling.name
+ hireling.name = data.newHirelingName
+
+ if not playerInFunction:makeCoinTransaction(data.offer, oldName .. " to " .. hireling.name) then
+ return playerInFunction:showInfoModal("Error", "Transaction error")
+ end
+
+ local lamp = playerInFunction:findHirelingLamp(hireling:getId())
+ if lamp then
+ lamp:setAttribute(ITEM_ATTRIBUTE_DESCRIPTION, "This mysterious lamp summons your very own personal hireling.\nThis item cannot be traded.\nThis magic lamp is the home of " .. hireling:getName() .. ".")
+ end
+ logger.debug("{} has been renamed to {}", oldName, hireling.name)
+ sendUpdatedStoreBalances(playerIdInFunction)
+ end
+
+ player:sendHirelingSelectionModal("Choose a Hireling", "Select a hireling below", functionCallback, { offer = offer, newHirelingName = newHirelingName })
+end
+
+function GameStore.processHirelingChangeNamePurchase(player, offer, productType, newHirelingName)
if player:getClient().version < 1200 then
return error({
code = 1,
@@ -1838,17 +1879,60 @@ function GameStore.processHirelingChangeNamePurchase(player, offer, productType,
end)
local message = "Close the store window to select which hireling should be renamed to " .. newHirelingName
+ local playerId = player:getId()
addPlayerEvent(sendStorePurchaseSuccessful, 200, playerId, message)
-
addPlayerEvent(HandleHirelingNameChange, 550, playerId, offer, newHirelingName)
else
- return addPlayerEvent(sendRequestPurchaseData, 250, playerId, offerId, GameStore.ClientOfferTypes.CLIENT_STORE_OFFER_NAMECHANGE)
+ return addPlayerEvent(sendRequestPurchaseData, 250, player:getId(), offer.id, GameStore.ClientOfferTypes.CLIENT_STORE_OFFER_NAMECHANGE)
end
end
-function GameStore.processHirelingChangeSexPurchase(player, offer)
- local playerId = player:getId()
+local function HandleHirelingSexChange(playerId, offer)
+ local player = Player(playerId)
+ if not player then
+ return
+ end
+
+ local functionCallback = function(playerIdInFunction, data, hireling)
+ local playerInFunction = Player(playerIdInFunction)
+ if not playerInFunction then
+ return
+ end
+
+ if not hireling then
+ return playerInFunction:showInfoModal("Error", "Your must select a hireling.")
+ end
+ if hireling.active > 0 then
+ return playerInFunction:showInfoModal("Error", "Your hireling must be inside his/her lamp.")
+ end
+
+ if not playerInFunction:makeCoinTransaction(data.offer, hireling:getName()) then
+ return playerInFunction:showInfoModal("Error", "Transaction error")
+ end
+
+ local changeTo, sexString, lookType
+ if hireling.sex == HIRELING_SEX.FEMALE then
+ changeTo = HIRELING_SEX.MALE
+ sexString = "male"
+ lookType = HIRELING_OUTFIT_DEFAULT.male
+ else
+ changeTo = HIRELING_SEX.FEMALE
+ sexString = "female"
+ lookType = HIRELING_OUTFIT_DEFAULT.female
+ end
+
+ hireling.sex = changeTo
+ hireling.looktype = lookType
+
+ logger.debug("{} sex was changed to {}", hireling:getName(), sexString)
+ sendUpdatedStoreBalances(playerIdInFunction)
+ end
+
+ player:sendHirelingSelectionModal("Choose a Hireling", "Select a hireling below", functionCallback, { offer = offer })
+end
+
+function GameStore.processHirelingChangeSexPurchase(player, offer)
if player:getClient().version < 1200 then
return error({
code = 1,
@@ -1857,8 +1941,8 @@ function GameStore.processHirelingChangeSexPurchase(player, offer)
end
local message = "Close the store window to select which hireling should have the sex changed."
+ local playerId = player:getId()
addPlayerEvent(sendStorePurchaseSuccessful, 200, playerId, message)
-
addPlayerEvent(HandleHirelingSexChange, 550, playerId, offer)
end
@@ -2154,75 +2238,3 @@ function Player:openStore(serviceName) --exporting the method so other scripts c
addPlayerEvent(sendShowStoreOffers, 50, playerId, category)
end
end
-
--- Hireling Helpers
-function HandleHirelingNameChange(playerId, offer, newHirelingName)
- local player = Player(playerId)
-
- local cb = function(playerId, data, hireling)
- local offer = data.offer
- local newHirelingName = data.newHirelingName
- local player = Player(playerId)
- if not hireling then
- return player:showInfoModal("Error", "Your must select a hireling.")
- end
-
- if hireling.active > 0 then
- return player:showInfoModal("Error", "Your hireling must be inside his/her lamp.")
- end
-
- local oldName = hireling.name
- hireling.name = newHirelingName
-
- if not player:makeCoinTransaction(data.offer, oldName .. " to " .. newHirelingName) then
- return player:showInfoModal("Error", "Transaction error")
- end
-
- local lamp = player:findHirelingLamp(hireling:getId())
- if lamp then
- lamp:setAttribute(ITEM_ATTRIBUTE_DESCRIPTION, "This mysterious lamp summons your very own personal hireling.\nThis item cannot be traded.\nThis magic lamp is the home of " .. hireling:getName() .. ".")
- end
- logger.debug("{} has been renamed to {}", oldName, newHirelingName)
- sendUpdatedStoreBalances(playerId)
- end
-
- player:sendHirelingSelectionModal("Choose a Hireling", "Select a hireling below", cb, { offer = offer, newHirelingName = newHirelingName })
-end
-
-function HandleHirelingSexChange(playerId, offer)
- local player = Player(playerId)
-
- local cb = function(playerId, data, hireling)
- local player = Player(playerId)
- if not hireling then
- return player:showInfoModal("Error", "Your must select a hireling.")
- end
-
- if hireling.active > 0 then
- return player:showInfoModal("Error", "Your hireling must be inside his/her lamp.")
- end
-
- if not player:makeCoinTransaction(data.offer, hireling:getName()) then
- return player:showInfoModal("Error", "Transaction error")
- end
-
- local changeTo, sexString, lookType
- if hireling.sex == HIRELING_SEX.FEMALE then
- changeTo = HIRELING_SEX.MALE
- sexString = "male"
- lookType = HIRELING_OUTFIT_DEFAULT.male
- else
- changeTo = HIRELING_SEX.FEMALE
- sexString = "female"
- lookType = HIRELING_OUTFIT_DEFAULT.female
- end
-
- hireling.sex = changeTo
- hireling.looktype = lookType
-
- logger.debug("{} sex was changed to {}", hireling:getName(), sexString)
- sendUpdatedStoreBalances(playerId)
- end
-
- player:sendHirelingSelectionModal("Choose a Hireling", "Select a hireling below", cb, { offer = offer })
-end
diff --git a/data/scripts/actions/items/blueberry_cupcake.lua b/data/scripts/actions/items/blueberry_cupcake.lua
new file mode 100644
index 00000000000..f645e852101
--- /dev/null
+++ b/data/scripts/actions/items/blueberry_cupcake.lua
@@ -0,0 +1,18 @@
+local blueberryCupcake = Action()
+
+function blueberryCupcake.onUse(player, item, fromPosition, target, toPosition, isHotkey)
+ if player:hasExhaustion("blueberry-cupcake-cooldown") then
+ player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You need to wait before using it again.")
+ return true
+ end
+
+ player:addMana(player:getMaxMana())
+ player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Your mana has been refilled.")
+ player:say("Mmmm.", TALKTYPE_MONSTER_SAY)
+ player:setExhaustion("blueberry-cupcake-cooldown", 10 * 60)
+ item:remove(1)
+ return true
+end
+
+blueberryCupcake:id(28484)
+blueberryCupcake:register()
diff --git a/data/scripts/actions/items/lemon_cupcake.lua b/data/scripts/actions/items/lemon_cupcake.lua
new file mode 100644
index 00000000000..3cf085d8ad8
--- /dev/null
+++ b/data/scripts/actions/items/lemon_cupcake.lua
@@ -0,0 +1,24 @@
+local distanceCondition = Condition(CONDITION_ATTRIBUTES)
+distanceCondition:setParameter(CONDITION_PARAM_BUFF_SPELL, 1)
+distanceCondition:setParameter(CONDITION_PARAM_TICKS, 60 * 60 * 1000)
+distanceCondition:setParameter(CONDITION_PARAM_SKILL_DISTANCE, 10)
+distanceCondition:setParameter(CONDITION_PARAM_FORCEUPDATE, true)
+
+local lemonCupcake = Action()
+
+function lemonCupcake.onUse(player, item, fromPosition, target, toPosition, isHotkey)
+ if player:hasExhaustion("lemon-cupcake-cooldown") then
+ player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You need to wait before using it again.")
+ return true
+ end
+
+ player:addCondition(distanceCondition)
+ player:sendTextMessage(MESSAGE_FAILURE, "You feel more focused.")
+ player:say("Mmmm.", TALKTYPE_MONSTER_SAY)
+ player:setExhaustion("lemon-cupcake-cooldown", 10 * 60)
+ item:remove(1)
+ return true
+end
+
+lemonCupcake:id(28486)
+lemonCupcake:register()
diff --git a/data/scripts/actions/items/potions.lua b/data/scripts/actions/items/potions.lua
index 02e92349363..473796d79df 100644
--- a/data/scripts/actions/items/potions.lua
+++ b/data/scripts/actions/items/potions.lua
@@ -89,10 +89,13 @@ function flaskPotion.onUse(player, item, fromPosition, target, toPosition, isHot
local deactivatedFlasks = player:kv():get("talkaction.potions.flask") or false
if not deactivatedFlasks then
local container = Container(item:getParent().uid)
- local inbox = player:getSlotItem(CONST_SLOT_STORE_INBOX)
-
- if fromPosition.x == CONTAINER_POSITION and container ~= inbox and container:getEmptySlots() ~= 0 then
- container:addItem(potion.flask, 1)
+ if container then
+ local storeInbox = player:getSlotItem(CONST_SLOT_STORE_INBOX)
+ if fromPosition.x == CONTAINER_POSITION and container ~= storeInbox and container:getEmptySlots() ~= 0 then
+ container:addItem(potion.flask, 1)
+ else
+ player:addItem(potion.flask, 1)
+ end
else
Game.createItem(potion.flask, 1, fromPosition)
end
diff --git a/data/scripts/actions/items/strawberry_cupcake.lua b/data/scripts/actions/items/strawberry_cupcake.lua
new file mode 100644
index 00000000000..7ee7ec75764
--- /dev/null
+++ b/data/scripts/actions/items/strawberry_cupcake.lua
@@ -0,0 +1,18 @@
+local strawberryCupcake = Action()
+
+function strawberryCupcake.onUse(player, item, fromPosition, target, toPosition, isHotkey)
+ if player:hasExhaustion("strawberry-cupcake-cooldown") then
+ player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You need to wait before using it again.")
+ return true
+ end
+
+ player:addHealth(player:getMaxHealth())
+ player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Your health has been refilled.")
+ player:say("Mmmm.", TALKTYPE_MONSTER_SAY)
+ player:setExhaustion("strawberry-cupcake-cooldown", 10 * 60)
+ item:remove(1)
+ return true
+end
+
+strawberryCupcake:id(28485)
+strawberryCupcake:register()
diff --git a/data/scripts/creaturescripts/player/offline_training.lua b/data/scripts/creaturescripts/player/offline_training.lua
index abfb0b94b3d..4466c6ee0e3 100644
--- a/data/scripts/creaturescripts/player/offline_training.lua
+++ b/data/scripts/creaturescripts/player/offline_training.lua
@@ -12,7 +12,7 @@ function offlineTraining.onLogin(player)
player:setOfflineTrainingSkill(SKILL_NONE)
if offlineTime < 600 then
- player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You must be logged out for more than 10 minutes to start offline training.")
+ player:sendTextMessage(MESSAGE_OFFLINE_TRAINING, "You must be logged out for more than 10 minutes to start offline training.")
return true
end
@@ -50,15 +50,15 @@ function offlineTraining.onLogin(player)
end
text = string.format("%s.", text)
- player:sendTextMessage(MESSAGE_EVENT_ADVANCE, text)
+ player:sendTextMessage(MESSAGE_OFFLINE_TRAINING, text)
local vocation = player:getVocation()
local promotion = vocation:getPromotion()
local topVocation = not promotion and vocation or promotion
-
local updateSkills = false
+
if table.contains({ SKILL_CLUB, SKILL_SWORD, SKILL_AXE, SKILL_DISTANCE }, offlineTrainingSkill) then
- local modifier = topVocation:getBaseAttackSpeed() / 1000
+ local modifier = topVocation:getBaseAttackSpeed() / 1000 / configManager.getFloat(configKeys.RATE_OFFLINE_TRAINING_SPEED)
updateSkills = player:addOfflineTrainingTries(offlineTrainingSkill, (trainingTime / modifier) / (offlineTrainingSkill == SKILL_DISTANCE and 4 or 2))
elseif offlineTrainingSkill == SKILL_MAGLEVEL then
local gainTicks = topVocation:getManaGainTicks() * 2
diff --git a/data/scripts/spells/conjuring/conjure_diamond_arrow.lua b/data/scripts/spells/conjuring/conjure_diamond_arrow.lua
deleted file mode 100644
index 2ab4bbe0647..00000000000
--- a/data/scripts/spells/conjuring/conjure_diamond_arrow.lua
+++ /dev/null
@@ -1,21 +0,0 @@
-local spell = Spell("instant")
-
-function spell.onCastSpell(creature, variant)
- return creature:conjureItem(0, 25757, 100, CONST_ME_MAGIC_BLUE)
-end
-
-spell:group("support")
-spell:id(192)
-spell:name("Conjure Diamond Arrow")
-spell:words("exevo gran con hur")
-spell:cooldown(2 * 1000)
-spell:groupCooldown(2 * 1000)
-spell:level(150)
-spell:mana(1000)
-spell:soul(0)
-spell:isPremium(true)
-spell:isSelfTarget(true)
-spell:isAggressive(false)
-spell:vocation("paladin;true", "royal paladin;true")
-spell:needLearn(false)
-spell:register()
diff --git a/data/scripts/spells/conjuring/conjure_spectral_bolt.lua b/data/scripts/spells/conjuring/conjure_spectral_bolt.lua
deleted file mode 100644
index 336eb423139..00000000000
--- a/data/scripts/spells/conjuring/conjure_spectral_bolt.lua
+++ /dev/null
@@ -1,21 +0,0 @@
-local spell = Spell("instant")
-
-function spell.onCastSpell(creature, variant)
- return creature:conjureItem(0, 35902, 100, CONST_ME_MAGIC_BLUE)
-end
-
-spell:group("support")
-spell:id(193)
-spell:name("Conjure Spectral Bolt")
-spell:words("exevo gran con vis")
-spell:cooldown(2 * 1000)
-spell:groupCooldown(2 * 1000)
-spell:level(150)
-spell:mana(1000)
-spell:soul(0)
-spell:isPremium(true)
-spell:isSelfTarget(true)
-spell:isAggressive(false)
-spell:vocation("paladin;true", "royal paladin;true")
-spell:needLearn(false)
-spell:register()
diff --git a/src/canary_server.cpp b/src/canary_server.cpp
index 56cd53bf567..0961bc93fde 100644
--- a/src/canary_server.cpp
+++ b/src/canary_server.cpp
@@ -61,6 +61,7 @@ int CanaryServer::run() {
loadConfigLua();
logger.info("Server protocol: {}.{}{}", CLIENT_VERSION_UPPER, CLIENT_VERSION_LOWER, g_configManager().getBoolean(OLD_PROTOCOL, __FUNCTION__) ? " and 10x allowed!" : "");
+#ifdef FEATURE_METRICS
metrics::Options metricsOptions;
metricsOptions.enablePrometheusExporter = g_configManager().getBoolean(METRICS_ENABLE_PROMETHEUS, __FUNCTION__);
if (metricsOptions.enablePrometheusExporter) {
@@ -71,7 +72,7 @@ int CanaryServer::run() {
metricsOptions.ostreamOptions.export_interval_millis = std::chrono::milliseconds(g_configManager().getNumber(METRICS_OSTREAM_INTERVAL, __FUNCTION__));
}
g_metrics().init(metricsOptions);
-
+#endif
rsa.start();
initializeDatabase();
loadModules();
diff --git a/src/config/config_enums.hpp b/src/config/config_enums.hpp
index b9b857f435c..4abf29c04cb 100644
--- a/src/config/config_enums.hpp
+++ b/src/config/config_enums.hpp
@@ -36,10 +36,10 @@ enum ConfigKey_t : uint16_t {
CLASSIC_ATTACK_SPEED,
CLEAN_PROTECTION_ZONES,
COMBAT_CHAIN_DELAY,
- COMBAT_CHAIN_TARGETS,
COMBAT_CHAIN_SKILL_FORMULA_AXE,
COMBAT_CHAIN_SKILL_FORMULA_CLUB,
COMBAT_CHAIN_SKILL_FORMULA_SWORD,
+ COMBAT_CHAIN_TARGETS,
COMPRESSION_LEVEL,
CONVERT_UNSAFE_SCRIPTS,
CORE_DIRECTORY,
@@ -155,6 +155,7 @@ enum ConfigKey_t : uint16_t {
METRICS_PROMETHEUS_ADDRESS,
MIN_DELAY_BETWEEN_CONDITIONS,
MIN_ELEMENTAL_RESISTANCE,
+ MIN_TOWN_ID_TO_BANK_TRANSFER,
MOMENTUM_CHANCE_FORMULA_A,
MOMENTUM_CHANCE_FORMULA_B,
MOMENTUM_CHANCE_FORMULA_C,
@@ -178,6 +179,7 @@ enum ConfigKey_t : uint16_t {
OWNER_NAME,
PARALLELISM,
PARTY_AUTO_SHARE_EXPERIENCE,
+ PARTY_SHARE_RANGE_MULTIPLIER,
PARTY_LIST_MAX_DISTANCE,
PARTY_SHARE_LOOT_BOOSTS_DIMINISHING_FACTOR,
PARTY_SHARE_LOOT_BOOSTS,
diff --git a/src/config/configmanager.cpp b/src/config/configmanager.cpp
index c1702672e71..8d4ba7a77da 100644
--- a/src/config/configmanager.cpp
+++ b/src/config/configmanager.cpp
@@ -166,6 +166,9 @@ bool ConfigManager::load() {
loadBoolConfig(L, XP_DISPLAY_MODE, "experienceDisplayRates", true);
loadFloatConfig(L, BESTIARY_RATE_CHARM_SHOP_PRICE, "bestiaryRateCharmShopPrice", 1.0);
+ loadFloatConfig(L, COMBAT_CHAIN_SKILL_FORMULA_AXE, "combatChainSkillFormulaAxe", 0.9);
+ loadFloatConfig(L, COMBAT_CHAIN_SKILL_FORMULA_CLUB, "combatChainSkillFormulaClub", 0.7);
+ loadFloatConfig(L, COMBAT_CHAIN_SKILL_FORMULA_SWORD, "combatChainSkillFormulaSword", 1.1);
loadFloatConfig(L, FORGE_AMOUNT_MULTIPLIER, "forgeAmountMultiplier", 3.0);
loadFloatConfig(L, HAZARD_EXP_BONUS_MULTIPLIER, "hazardExpBonusMultiplier", 2.0);
loadFloatConfig(L, LOYALTY_BONUS_PERCENTAGE_MULTIPLIER, "loyaltyBonusPercentageMultiplier", 1.0);
@@ -218,9 +221,6 @@ bool ConfigManager::load() {
loadIntConfig(L, CHECK_EXPIRED_MARKET_OFFERS_EACH_MINUTES, "checkExpiredMarketOffersEachMinutes", 60);
loadIntConfig(L, COMBAT_CHAIN_DELAY, "combatChainDelay", 50);
loadIntConfig(L, COMBAT_CHAIN_TARGETS, "combatChainTargets", 5);
- loadFloatConfig(L, COMBAT_CHAIN_SKILL_FORMULA_AXE, "combatChainSkillFormulaAxe", 0.9);
- loadFloatConfig(L, COMBAT_CHAIN_SKILL_FORMULA_CLUB, "combatChainSkillFormulaClub", 0.7);
- loadFloatConfig(L, COMBAT_CHAIN_SKILL_FORMULA_SWORD, "combatChainSkillFormulaSword", 1.1);
loadIntConfig(L, COMPRESSION_LEVEL, "packetCompressionLevel", 6);
loadIntConfig(L, CRITICALCHANCE, "criticalChance", 10);
loadIntConfig(L, DAY_KILLS_TO_RED, "dayKillsToRedSkull", 3);
@@ -287,6 +287,7 @@ bool ConfigManager::load() {
loadIntConfig(L, METRICS_OSTREAM_INTERVAL, "metricsOstreamInterval", 1000);
loadIntConfig(L, MIN_DELAY_BETWEEN_CONDITIONS, "minDelayBetweenConditions", 0);
loadIntConfig(L, MIN_ELEMENTAL_RESISTANCE, "minElementalResistance", -200);
+ loadIntConfig(L, MIN_TOWN_ID_TO_BANK_TRANSFER, "minTownIdToBankTransfer", 3);
loadIntConfig(L, MONTH_KILLS_TO_RED, "monthKillsToRedSkull", 10);
loadIntConfig(L, MULTIPLIER_ATTACKONFIST, "multiplierSpeedOnFist", 5);
loadIntConfig(L, ORANGE_SKULL_DURATION, "orangeSkullDuration", 7);
@@ -317,6 +318,7 @@ bool ConfigManager::load() {
loadIntConfig(L, STAMINA_PZ_GAIN, "staminaPzGain", 1);
loadIntConfig(L, STAMINA_TRAINER_DELAY, "staminaTrainerDelay", 5);
loadIntConfig(L, STAMINA_TRAINER_GAIN, "staminaTrainerGain", 1);
+ loadFloatConfig(L, PARTY_SHARE_RANGE_MULTIPLIER, "partyShareRangeMultiplier", 1.5f);
loadIntConfig(L, START_STREAK_LEVEL, "startStreakLevel", 0);
loadIntConfig(L, STATUSQUERY_TIMEOUT, "statusTimeout", 5000);
loadIntConfig(L, STORE_COIN_PACKET, "coinPacketSize", 25);
diff --git a/src/creatures/combat/condition.cpp b/src/creatures/combat/condition.cpp
index d54a3deb1d0..9d0f6962884 100644
--- a/src/creatures/combat/condition.cpp
+++ b/src/creatures/combat/condition.cpp
@@ -2041,7 +2041,11 @@ bool ConditionFeared::executeCondition(std::shared_ptr creature, int32
}
if (getFleePath(creature, currentPos, listDir)) {
- g_dispatcher().addEvent(std::bind(&Game::forcePlayerAutoWalk, &g_game(), creature->getID(), listDir.data()), "ConditionFeared::executeCondition");
+ g_dispatcher().addEvent([id = creature->getID(), listDir = listDir.data()] {
+ g_game().forcePlayerAutoWalk(id, listDir);
+ },
+ "ConditionFeared::executeCondition");
+
g_logger().debug("[ConditionFeared::executeCondition] Walking Scheduled");
}
}
diff --git a/src/creatures/creature.cpp b/src/creatures/creature.cpp
index d17ee454402..6101ff0473d 100644
--- a/src/creatures/creature.cpp
+++ b/src/creatures/creature.cpp
@@ -258,8 +258,8 @@ void Creature::addEventWalk(bool firstStep) {
}
self->eventWalk = g_dispatcher().scheduleEvent(
- static_cast(ticks), std::bind(&Game::checkCreatureWalk, &g_game(), self->getID()),
- "Creature::checkCreatureWalk"
+ static_cast(ticks),
+ [creatureId = self->getID()] { g_game().checkCreatureWalk(creatureId); }, "Creature::checkCreatureWalk"
);
});
}
@@ -600,7 +600,7 @@ void Creature::onCreatureMove(const std::shared_ptr &creature, const s
if (followCreature && (creature == getCreature() || creature == followCreature)) {
if (hasFollowPath) {
isUpdatingPath = true;
- g_dispatcher().addEvent(std::bind(&Game::updateCreatureWalk, &g_game(), getID()), "Game::updateCreatureWalk");
+ g_dispatcher().addEvent([creatureId = getID()] { g_game().updateCreatureWalk(creatureId); }, "Game::updateCreatureWalk");
}
if (newPos.z != oldPos.z || !canSee(followCreature->getPosition())) {
@@ -615,7 +615,7 @@ void Creature::onCreatureMove(const std::shared_ptr &creature, const s
} else {
if (hasExtraSwing()) {
// our target is moving lets see if we can get in hit
- g_dispatcher().addEvent(std::bind(&Game::checkCreatureAttack, &g_game(), getID()), "Game::checkCreatureAttack");
+ g_dispatcher().addEvent([creatureId = getID()] { g_game().checkCreatureAttack(creatureId); }, "Game::checkCreatureAttack");
}
if (newTile->getZoneType() != oldTile->getZoneType()) {
@@ -813,11 +813,21 @@ bool Creature::dropCorpse(std::shared_ptr lastHitCreature, std::shared
player->sendLootMessage(lootMessage.str());
}
- if (player->checkAutoLoot(monster->isRewardBoss()) && corpseContainer && mostDamageCreature->getPlayer()) {
- g_dispatcher().addEvent(
- std::bind(&Game::playerQuickLootCorpse, &g_game(), player, corpseContainer, corpse->getPosition()),
- "Game::playerQuickLootCorpse"
- );
+ stdext::arraylist dirList(128);
+ FindPathParams fpp;
+ fpp.minTargetDist = 0;
+ fpp.maxTargetDist = 1;
+ fpp.fullPathSearch = true;
+ fpp.clearSight = true;
+ fpp.maxSearchDist = 0;
+
+ auto isReachable = g_game().map.getPathMatching(player->getPosition(), dirList, FrozenPathingConditionCall(corpse->getPosition()), fpp);
+
+ if (player->checkAutoLoot(monster->isRewardBoss()) && corpseContainer && mostDamageCreature->getPlayer() && isReachable) {
+ g_dispatcher().addEvent([player, corpseContainer, corpsePosition = corpse->getPosition()] {
+ g_game().playerQuickLootCorpse(player, corpseContainer, corpsePosition);
+ },
+ "Game::playerQuickLootCorpse");
}
}
}
@@ -861,7 +871,7 @@ void Creature::changeHealth(int32_t healthChange, bool sendHealthChange /* = tru
g_game().addCreatureHealth(static_self_cast());
}
if (health <= 0) {
- g_dispatcher().addEvent(std::bind(&Game::executeDeath, &g_game(), getID()), "Game::executeDeath");
+ g_dispatcher().addEvent([creatureId = getID()] { g_game().executeDeath(creatureId); }, "Game::executeDeath");
}
}
@@ -1401,9 +1411,7 @@ void Creature::removeCondition(ConditionType_t conditionType, ConditionId_t cond
int32_t walkDelay = getWalkDelay();
if (walkDelay > 0) {
g_dispatcher().scheduleEvent(
- walkDelay,
- std::bind(&Game::forceRemoveCondition, &g_game(), getID(), conditionType, conditionId),
- "Game::forceRemoveCondition"
+ walkDelay, [creatureId = getID(), conditionType, conditionId] { g_game().forceRemoveCondition(creatureId, conditionType, conditionId); }, "Game::forceRemoveCondition"
);
return;
}
diff --git a/src/creatures/interactions/chat.cpp b/src/creatures/interactions/chat.cpp
index f30c3f219e3..e16af670fcc 100644
--- a/src/creatures/interactions/chat.cpp
+++ b/src/creatures/interactions/chat.cpp
@@ -81,7 +81,9 @@ bool ChatChannel::addUser(const std::shared_ptr &player) {
if (id == CHANNEL_GUILD) {
const auto guild = player->getGuild();
if (guild && !guild->getMotd().empty()) {
- g_dispatcher().scheduleEvent(150, std::bind(&Game::sendGuildMotd, &g_game(), player->getID()), "Game::sendGuildMotd");
+ g_dispatcher().scheduleEvent(
+ 150, [playerId = player->getID()] { g_game().sendGuildMotd(playerId); }, "Game::sendGuildMotd"
+ );
}
}
diff --git a/src/creatures/monsters/monster.cpp b/src/creatures/monsters/monster.cpp
index 5f31c67aa72..f15616d6af5 100644
--- a/src/creatures/monsters/monster.cpp
+++ b/src/creatures/monsters/monster.cpp
@@ -668,7 +668,7 @@ bool Monster::selectTarget(const std::shared_ptr &creature) {
if (isHostile() || isSummon()) {
if (setAttackedCreature(creature)) {
- g_dispatcher().addEvent(std::bind(&Game::checkCreatureAttack, &g_game(), getID()), "Game::checkCreatureAttack");
+ g_dispatcher().addEvent([creatureId = getID()] { g_game().checkCreatureAttack(creatureId); }, "Game::checkCreatureAttack");
}
}
return setFollowCreature(creature);
diff --git a/src/creatures/monsters/spawns/spawn_monster.cpp b/src/creatures/monsters/spawns/spawn_monster.cpp
index aec222d723a..21eab1a7c0b 100644
--- a/src/creatures/monsters/spawns/spawn_monster.cpp
+++ b/src/creatures/monsters/spawns/spawn_monster.cpp
@@ -141,7 +141,9 @@ bool SpawnsMonster::isInZone(const Position ¢erPos, int32_t radius, const Po
void SpawnMonster::startSpawnMonsterCheck() {
if (checkSpawnMonsterEvent == 0) {
- checkSpawnMonsterEvent = g_dispatcher().scheduleEvent(getInterval(), std::bind(&SpawnMonster::checkSpawnMonster, this), "SpawnMonster::checkSpawnMonster");
+ checkSpawnMonsterEvent = g_dispatcher().scheduleEvent(
+ getInterval(), [this] { checkSpawnMonster(); }, "SpawnMonster::checkSpawnMonster"
+ );
}
}
@@ -178,6 +180,7 @@ bool SpawnMonster::spawnMonster(uint32_t spawnMonsterId, spawnBlock_t &sb, const
return false;
}
} else {
+ g_logger().debug("[SpawnMonster] Spawning {} at {}", monsterType->name, sb.pos.toString());
if (!g_game().placeCreature(monster, sb.pos, false, true)) {
return false;
}
@@ -225,7 +228,7 @@ void SpawnMonster::startup(bool delayed) {
continue;
}
if (delayed) {
- g_dispatcher().addEvent(std::bind(&SpawnMonster::scheduleSpawn, this, spawnMonsterId, sb, mType, 0, true), "SpawnMonster::startup");
+ g_dispatcher().addEvent([this, spawnMonsterId, &sb, mType] { scheduleSpawn(spawnMonsterId, sb, mType, 0, true); }, "SpawnMonster::startup");
} else {
scheduleSpawn(spawnMonsterId, sb, mType, 0, true);
}
@@ -258,14 +261,16 @@ void SpawnMonster::checkSpawnMonster() {
}
if (mType->info.isBlockable) {
- spawnMonster(spawnMonsterId, sb, mType, true);
+ spawnMonster(spawnMonsterId, sb, mType);
} else {
scheduleSpawn(spawnMonsterId, sb, mType, 3 * NONBLOCKABLE_SPAWN_MONSTER_INTERVAL);
}
}
if (spawnedMonsterMap.size() < spawnMonsterMap.size()) {
- checkSpawnMonsterEvent = g_dispatcher().scheduleEvent(getInterval(), std::bind(&SpawnMonster::checkSpawnMonster, this), "SpawnMonster::checkSpawnMonster");
+ checkSpawnMonsterEvent = g_dispatcher().scheduleEvent(
+ getInterval(), [this] { checkSpawnMonster(); }, "SpawnMonster::checkSpawnMonster"
+ );
}
}
@@ -274,7 +279,9 @@ void SpawnMonster::scheduleSpawn(uint32_t spawnMonsterId, spawnBlock_t &sb, cons
spawnMonster(spawnMonsterId, sb, mType, startup);
} else {
g_game().addMagicEffect(sb.pos, CONST_ME_TELEPORT);
- g_dispatcher().scheduleEvent(NONBLOCKABLE_SPAWN_MONSTER_INTERVAL, std::bind(&SpawnMonster::scheduleSpawn, this, spawnMonsterId, sb, mType, interval - NONBLOCKABLE_SPAWN_MONSTER_INTERVAL, startup), "SpawnMonster::scheduleSpawn");
+ g_dispatcher().scheduleEvent(
+ NONBLOCKABLE_SPAWN_MONSTER_INTERVAL, [=, this, &sb] { scheduleSpawn(spawnMonsterId, sb, mType, interval - NONBLOCKABLE_SPAWN_MONSTER_INTERVAL, startup); }, "SpawnMonster::scheduleSpawn"
+ );
}
}
diff --git a/src/creatures/npcs/npc.cpp b/src/creatures/npcs/npc.cpp
index 0f9f60cec9b..d347ec6b66c 100644
--- a/src/creatures/npcs/npc.cpp
+++ b/src/creatures/npcs/npc.cpp
@@ -351,7 +351,9 @@ void Npc::onPlayerSellAllLoot(uint32_t playerId, uint16_t itemId, bool ignore, u
return;
}
if (hasMore) {
- g_dispatcher().scheduleEvent(SCHEDULER_MINTICKS, std::bind(&Npc::onPlayerSellAllLoot, this, player->getID(), itemId, ignore, totalPrice), __FUNCTION__);
+ g_dispatcher().scheduleEvent(
+ SCHEDULER_MINTICKS, [this, playerId = player->getID(), itemId, ignore, totalPrice] { onPlayerSellAllLoot(playerId, itemId, ignore, totalPrice); }, __FUNCTION__
+ );
return;
}
ss << "You sold all of the items from your loot pouch for ";
@@ -366,7 +368,9 @@ void Npc::onPlayerSellItem(std::shared_ptr player, uint16_t itemId, uint
return;
}
if (itemId == ITEM_GOLD_POUCH) {
- g_dispatcher().scheduleEvent(SCHEDULER_MINTICKS, std::bind(&Npc::onPlayerSellAllLoot, this, player->getID(), itemId, ignore, 0), __FUNCTION__);
+ g_dispatcher().scheduleEvent(
+ SCHEDULER_MINTICKS, [this, playerId = player->getID(), itemId, ignore] { onPlayerSellAllLoot(playerId, itemId, ignore, 0); }, __FUNCTION__
+ );
return;
}
diff --git a/src/creatures/npcs/spawns/spawn_npc.cpp b/src/creatures/npcs/spawns/spawn_npc.cpp
index 7fd99d6c37f..968deca5331 100644
--- a/src/creatures/npcs/spawns/spawn_npc.cpp
+++ b/src/creatures/npcs/spawns/spawn_npc.cpp
@@ -131,7 +131,9 @@ bool SpawnsNpc::isInZone(const Position ¢erPos, int32_t radius, const Positi
void SpawnNpc::startSpawnNpcCheck() {
if (checkSpawnNpcEvent == 0) {
- checkSpawnNpcEvent = g_dispatcher().scheduleEvent(getInterval(), std::bind(&SpawnNpc::checkSpawnNpc, this), "SpawnNpc::checkSpawnNpc");
+ checkSpawnNpcEvent = g_dispatcher().scheduleEvent(
+ getInterval(), [this] { checkSpawnNpc(); }, "SpawnNpc::checkSpawnNpc"
+ );
}
}
@@ -217,7 +219,9 @@ void SpawnNpc::checkSpawnNpc() {
}
if (spawnedNpcMap.size() < spawnNpcMap.size()) {
- checkSpawnNpcEvent = g_dispatcher().scheduleEvent(getInterval(), std::bind(&SpawnNpc::checkSpawnNpc, this), __FUNCTION__);
+ checkSpawnNpcEvent = g_dispatcher().scheduleEvent(
+ getInterval(), [this] { checkSpawnNpc(); }, __FUNCTION__
+ );
}
}
@@ -226,7 +230,9 @@ void SpawnNpc::scheduleSpawnNpc(uint32_t spawnId, spawnBlockNpc_t &sb, uint16_t
spawnNpc(spawnId, sb.npcType, sb.pos, sb.direction);
} else {
g_game().addMagicEffect(sb.pos, CONST_ME_TELEPORT);
- g_dispatcher().scheduleEvent(1400, std::bind(&SpawnNpc::scheduleSpawnNpc, this, spawnId, sb, interval - NONBLOCKABLE_SPAWN_NPC_INTERVAL), __FUNCTION__);
+ g_dispatcher().scheduleEvent(
+ 1400, [=, this, &sb] { scheduleSpawnNpc(spawnId, sb, interval - NONBLOCKABLE_SPAWN_NPC_INTERVAL); }, __FUNCTION__
+ );
}
}
diff --git a/src/creatures/players/grouping/party.cpp b/src/creatures/players/grouping/party.cpp
index 880fc77594f..c7d6fd48363 100644
--- a/src/creatures/players/grouping/party.cpp
+++ b/src/creatures/players/grouping/party.cpp
@@ -491,6 +491,10 @@ SharedExpStatus_t Party::getMemberSharedExperienceStatus(std::shared_ptr
return SHAREDEXP_OK;
}
+float Party::shareRangeMultiplier() const {
+ return g_configManager().getFloat(PARTY_SHARE_RANGE_MULTIPLIER, __FUNCTION__);
+}
+
uint32_t Party::getHighestLevel() {
auto leader = getLeader();
if (!leader) {
@@ -507,7 +511,7 @@ uint32_t Party::getHighestLevel() {
}
uint32_t Party::getMinLevel() {
- return static_cast(std::ceil((static_cast(getHighestLevel()) * 2) / 3));
+ return static_cast(std::ceil(static_cast(getHighestLevel()) / shareRangeMultiplier()));
}
uint32_t Party::getLowestLevel() {
@@ -525,7 +529,7 @@ uint32_t Party::getLowestLevel() {
}
uint32_t Party::getMaxLevel() {
- return static_cast(std::floor((static_cast(getLowestLevel()) * 3) / 2));
+ return static_cast(std::floor(static_cast(getLowestLevel()) * shareRangeMultiplier()));
}
bool Party::isPlayerActive(std::shared_ptr player) {
@@ -533,7 +537,6 @@ bool Party::isPlayerActive(std::shared_ptr player) {
if (it == ticksMap.end()) {
return false;
}
-
uint64_t timeDiff = OTSYS_TIME() - it->second;
return timeDiff <= 2 * 60 * 1000;
}
diff --git a/src/creatures/players/grouping/party.hpp b/src/creatures/players/grouping/party.hpp
index a356d1a032b..5da0f4e0647 100644
--- a/src/creatures/players/grouping/party.hpp
+++ b/src/creatures/players/grouping/party.hpp
@@ -133,6 +133,7 @@ class Party : public SharedObject {
uint32_t getLowestLevel();
uint32_t getMinLevel();
uint32_t getMaxLevel();
+ float shareRangeMultiplier() const;
std::map ticksMap;
diff --git a/src/creatures/players/player.cpp b/src/creatures/players/player.cpp
index 874089e5602..75e5b5ef2af 100644
--- a/src/creatures/players/player.cpp
+++ b/src/creatures/players/player.cpp
@@ -1934,7 +1934,7 @@ void Player::onCreatureMove(const std::shared_ptr &creature, const std
const auto &followCreature = getFollowCreature();
if (hasFollowPath && (creature == followCreature || (creature.get() == this && followCreature))) {
isUpdatingPath = false;
- g_dispatcher().addEvent(std::bind(&Game::updateCreatureWalk, &g_game(), getID()), "Game::updateCreatureWalk");
+ g_dispatcher().addEvent([creatureId = getID()] { g_game().updateCreatureWalk(creatureId); }, "Game::updateCreatureWalk");
}
if (creature != getPlayer()) {
@@ -4245,7 +4245,7 @@ bool Player::updateSaleShopList(std::shared_ptr- item) {
return true;
}
- g_dispatcher().addEvent(std::bind(&Game::updatePlayerSaleItems, &g_game(), getID()), "updatePlayerSaleItems");
+ g_dispatcher().addEvent([creatureId = getID()] { g_game().updatePlayerSaleItems(creatureId); }, "Game::updatePlayerSaleItems");
scheduledSaleUpdate = true;
return true;
}
@@ -4316,7 +4316,7 @@ bool Player::setAttackedCreature(std::shared_ptr creature) {
}
if (creature) {
- g_dispatcher().addEvent(std::bind(&Game::checkCreatureAttack, &g_game(), getID()), "Game::checkCreatureAttack");
+ g_dispatcher().addEvent([creatureId = getID()] { g_game().checkCreatureAttack(creatureId); }, "Game::checkCreatureAttack");
}
return true;
}
@@ -4376,7 +4376,11 @@ void Player::doAttacking(uint32_t) {
result = Weapon::useFist(static_self_cast(), attackedCreature);
}
- std::shared_ptr task = createPlayerTask(std::max(SCHEDULER_MINTICKS, delay), std::bind(&Game::checkCreatureAttack, &g_game(), getID()), "Game::checkCreatureAttack");
+ const auto &task = createPlayerTask(
+ std::max(SCHEDULER_MINTICKS, delay),
+ [playerId = getID()] { g_game().checkCreatureAttack(playerId); }, "Game::checkCreatureAttack"
+ );
+
if (!classicSpeed) {
setNextActionTask(task, false);
} else {
@@ -6448,7 +6452,7 @@ void Player::stowItem(std::shared_ptr
- item, uint32_t count, bool allItems)
// Stow locker items
std::shared_ptr depotLocker = getDepotLocker(getLastDepotId());
auto [itemVector, itemMap] = requestLockerItems(depotLocker);
- for (auto lockerItem : itemVector) {
+ for (const auto &lockerItem : itemVector) {
if (lockerItem == nullptr) {
break;
}
@@ -6459,7 +6463,7 @@ void Player::stowItem(std::shared_ptr
- item, uint32_t count, bool allItems)
}
} else if (item->getContainer()) {
itemDict = item->getContainer()->getStowableItems();
- for (std::shared_ptr
- containerItem : item->getContainer()->getItems(true)) {
+ for (const std::shared_ptr
- &containerItem : item->getContainer()->getItems(true)) {
uint32_t depotChest = g_configManager().getNumber(DEPOTCHEST, __FUNCTION__);
bool validDepot = depotChest > 0 && depotChest < 21;
if (g_configManager().getBoolean(STASH_MOVING, __FUNCTION__) && containerItem && !containerItem->isStackable() && validDepot) {
@@ -6469,10 +6473,10 @@ void Player::stowItem(std::shared_ptr
- item, uint32_t count, bool allItems)
}
}
} else {
- itemDict.push_back(std::pair, uint32_t>(item, count));
+ itemDict.emplace_back(item, count);
}
- if (itemDict.size() == 0) {
+ if (itemDict.empty()) {
sendCancelMessage("There is no stowable items on this container.");
return;
}
@@ -7776,7 +7780,7 @@ bool Player::canAutoWalk(const Position &toPosition, const std::function
// Check if can walk to the toPosition and send event to use function
stdext::arraylist listDir(128);
if (getPathTo(toPosition, listDir, 0, 1, true, true)) {
- g_dispatcher().addEvent(std::bind(&Game::playerAutoWalk, &g_game(), getID(), listDir.data()), __FUNCTION__);
+ g_dispatcher().addEvent([creatureId = getID(), dirs = listDir.data()] { g_game().playerAutoWalk(creatureId, dirs); }, __FUNCTION__);
std::shared_ptr task = createPlayerTask(delay, function, __FUNCTION__);
setNextWalkActionTask(task);
diff --git a/src/creatures/players/player.hpp b/src/creatures/players/player.hpp
index 592db179071..855b48a782b 100644
--- a/src/creatures/players/player.hpp
+++ b/src/creatures/players/player.hpp
@@ -657,6 +657,11 @@ class Player final : public Creature, public Cylinder, public Bankable {
return loginPosition;
}
const Position &getTemplePosition() const {
+ if (!town) {
+ static auto emptyPosition = Position();
+ return emptyPosition;
+ }
+
return town->getTemplePosition();
}
std::shared_ptr getTown() const {
diff --git a/src/game/bank/bank.cpp b/src/game/bank/bank.cpp
index 30345e0495b..d9a056396ce 100644
--- a/src/game/bank/bank.cpp
+++ b/src/game/bank/bank.cpp
@@ -80,18 +80,18 @@ const std::set deniedNames = {
"paladinsample"
};
-const uint32_t minTownId = 3;
-
bool Bank::transferTo(const std::shared_ptr destination, uint64_t amount) {
if (!destination) {
g_logger().error("Bank::transferTo: destination is nullptr");
return false;
}
+
auto bankable = getBankable();
if (!bankable) {
g_logger().error("Bank::transferTo: bankable is nullptr");
return false;
}
+
auto destinationBankable = destination->getBankable();
if (!destinationBankable) {
g_logger().error("Bank::transferTo: destinationBankable is nullptr");
@@ -102,11 +102,13 @@ bool Bank::transferTo(const std::shared_ptr destination, uint64_t amount)
if (destinationPlayer != nullptr) {
auto name = asLowerCaseString(destinationPlayer->getName());
replaceString(name, " ", "");
+
if (deniedNames.contains(name)) {
g_logger().warn("Bank::transferTo: denied name: {}", name);
return false;
}
- if (destinationPlayer->getTown()->getID() < minTownId) {
+
+ if (destinationPlayer->getTown()->getID() < g_configManager().getNumber(MIN_TOWN_ID_TO_BANK_TRANSFER, __FUNCTION__)) {
g_logger().warn("Bank::transferTo: denied town: {}", destinationPlayer->getTown()->getID());
return false;
}
diff --git a/src/game/game.cpp b/src/game/game.cpp
index 7adaf196dff..cac0b596ebf 100644
--- a/src/game/game.cpp
+++ b/src/game/game.cpp
@@ -207,6 +207,8 @@ Game::Game() {
// Create instance of IOWheel to Game class
m_IOWheel = std::make_unique();
+ wildcardTree = std::make_shared(false);
+
m_highscoreCategoriesNames = {
{ static_cast(HighscoreCategories_t::ACHIEVEMENTS), "Achievement Points" },
{ static_cast(HighscoreCategories_t::AXE_FIGHTING), "Axe Fighting" },
@@ -342,17 +344,30 @@ void Game::start(ServiceManager* manager) {
int minutes = tms->tm_min;
lightHour = (minutes * LIGHT_DAY_LENGTH) / 60;
- g_dispatcher().scheduleEvent(EVENT_MS + 1000, std::bind_front(&Game::createFiendishMonsters, this), "Game::createFiendishMonsters");
- g_dispatcher().scheduleEvent(EVENT_MS + 1000, std::bind_front(&Game::createInfluencedMonsters, this), "Game::createInfluencedMonsters");
-
- g_dispatcher().cycleEvent(EVENT_MS, std::bind_front(&Game::updateForgeableMonsters, this), "Game::updateForgeableMonsters");
- g_dispatcher().cycleEvent(EVENT_LIGHTINTERVAL_MS, std::bind(&Game::checkLight, this), "Game::checkLight");
- g_dispatcher().cycleEvent(EVENT_CHECK_CREATURE_INTERVAL, std::bind(&Game::checkCreatures, this), "Game::checkCreatures");
- g_dispatcher().cycleEvent(EVENT_IMBUEMENT_INTERVAL, std::bind(&Game::checkImbuements, this), "Game::checkImbuements");
+ g_dispatcher().scheduleEvent(
+ EVENT_MS + 1000, [this] { createFiendishMonsters(); }, "Game::createFiendishMonsters"
+ );
+ g_dispatcher().scheduleEvent(
+ EVENT_MS + 1000, [this] { createInfluencedMonsters(); }, "Game::createInfluencedMonsters"
+ );
+ g_dispatcher().cycleEvent(
+ EVENT_MS, [this] { updateForgeableMonsters(); }, "Game::updateForgeableMonsters"
+ );
+ g_dispatcher().cycleEvent(
+ EVENT_LIGHTINTERVAL_MS, [this] { checkLight(); }, "Game::checkLight"
+ );
+ g_dispatcher().cycleEvent(
+ EVENT_CHECK_CREATURE_INTERVAL, [this] { checkCreatures(); }, "Game::checkCreatures"
+ );
+ g_dispatcher().cycleEvent(
+ EVENT_IMBUEMENT_INTERVAL, [this] { checkImbuements(); }, "Game::checkImbuements"
+ );
g_dispatcher().cycleEvent(
EVENT_LUA_GARBAGE_COLLECTION, [this] { g_luaEnvironment().collectGarbage(); }, "Calling GC"
);
- g_dispatcher().cycleEvent(EVENT_REFRESH_MARKET_PRICES, std::bind_front(&Game::loadItemsPrice, this), "Game::loadItemsPrice");
+ g_dispatcher().cycleEvent(
+ EVENT_REFRESH_MARKET_PRICES, [this] { loadItemsPrice(); }, "Game::loadItemsPrice"
+ );
}
GameState_t Game::getGameState() const {
@@ -418,7 +433,7 @@ void Game::setGameState(GameState_t newState) {
saveMotdNum();
g_saveManager().saveAll();
- g_dispatcher().addEvent(std::bind(&Game::shutdown, this), "Game::shutdown");
+ g_dispatcher().addEvent([this] { shutdown(); }, "Game::shutdown");
break;
}
@@ -873,7 +888,7 @@ ReturnValue Game::getPlayerByNameWildcard(const std::string &s, std::shared_ptr<
if (s.back() == '~') {
const std::string &query = asLowerCaseString(s.substr(0, strlen - 1));
std::string result;
- ReturnValue ret = wildcardTree.findOne(query, result);
+ ReturnValue ret = wildcardTree->findOne(query, result);
if (ret != RETURNVALUE_NOERROR) {
return ret;
}
@@ -1165,9 +1180,11 @@ void Game::playerMoveThing(uint32_t playerId, const Position &fromPos, uint16_t
}
if (Position::areInRange<1, 1, 0>(movingCreature->getPosition(), player->getPosition())) {
- std::shared_ptr task = createPlayerTask(
+ const auto &task = createPlayerTask(
g_configManager().getNumber(PUSH_DELAY, __FUNCTION__),
- std::bind(&Game::playerMoveCreatureByID, this, player->getID(), movingCreature->getID(), movingCreature->getPosition(), tile->getPosition()),
+ [this, player, movingCreature, tile] {
+ playerMoveCreatureByID(player->getID(), movingCreature->getID(), movingCreature->getPosition(), tile->getPosition());
+ },
"Game::playerMoveCreatureByID"
);
player->setNextActionPushTask(task);
@@ -1208,8 +1225,9 @@ void Game::playerMoveCreatureByID(uint32_t playerId, uint32_t movingCreatureId,
void Game::playerMoveCreature(std::shared_ptr player, std::shared_ptr movingCreature, const Position &movingCreatureOrigPos, std::shared_ptr toTile) {
metrics::method_latency measure(__METHOD_NAME__);
if (!player->canDoAction()) {
- uint32_t delay = 600;
- std::shared_ptr task = createPlayerTask(delay, std::bind(&Game::playerMoveCreatureByID, this, player->getID(), movingCreature->getID(), movingCreatureOrigPos, toTile->getPosition()), "Game::playerMoveCreatureByID");
+ const auto &task = createPlayerTask(
+ 600, [this, player, movingCreature, toTile, movingCreatureOrigPos] { playerMoveCreatureByID(player->getID(), movingCreature->getID(), movingCreatureOrigPos, toTile->getPosition()); }, "Game::playerMoveCreatureByID"
+ );
player->setNextActionPushTask(task);
return;
@@ -1221,10 +1239,10 @@ void Game::playerMoveCreature(std::shared_ptr player, std::shared_ptr listDir(128);
if (player->getPathTo(movingCreatureOrigPos, listDir, 0, 1, true, true)) {
- g_dispatcher().addEvent(std::bind(&Game::playerAutoWalk, this, player->getID(), listDir.data()), "Game::playerAutoWalk");
-
- std::shared_ptr task = createPlayerTask(600, std::bind(&Game::playerMoveCreatureByID, this, player->getID(), movingCreature->getID(), movingCreatureOrigPos, toTile->getPosition()), "Game::playerMoveCreatureByID");
-
+ g_dispatcher().addEvent([this, playerId = player->getID(), listDir = listDir.data()] { playerAutoWalk(playerId, listDir); }, "Game::playerAutoWalk");
+ const auto &task = createPlayerTask(
+ 600, [this, player, movingCreature, toTile, movingCreatureOrigPos] { playerMoveCreatureByID(player->getID(), movingCreature->getID(), movingCreatureOrigPos, toTile->getPosition()); }, "Game::playerMoveCreatureByID"
+ );
player->pushEvent(true);
player->setNextActionPushTask(task);
} else {
@@ -1424,7 +1442,12 @@ void Game::playerMoveItemByPlayerID(uint32_t playerId, const Position &fromPos,
void Game::playerMoveItem(std::shared_ptr player, const Position &fromPos, uint16_t itemId, uint8_t fromStackPos, const Position &toPos, uint8_t count, std::shared_ptr
- item, std::shared_ptr toCylinder) {
if (!player->canDoAction()) {
uint32_t delay = player->getNextActionTime();
- std::shared_ptr task = createPlayerTask(delay, std::bind(&Game::playerMoveItemByPlayerID, this, player->getID(), fromPos, itemId, fromStackPos, toPos, count), "Game::playerMoveItemByPlayerID");
+ std::shared_ptr task = createPlayerTask(
+ delay, [this, playerId = player->getID(), fromPos, itemId, fromStackPos, toPos, count] {
+ playerMoveItemByPlayerID(playerId, fromPos, itemId, fromStackPos, toPos, count);
+ },
+ "Game::playerMoveItemByPlayerID"
+ );
player->setNextActionTask(task);
return;
}
@@ -1497,16 +1520,6 @@ void Game::playerMoveItem(std::shared_ptr player, const Position &fromPo
return;
}
- if (isTryingToStow(toPos, toCylinder)) {
- player->stowItem(item, count, false);
- return;
- }
-
- if (!item->isPushable() || item->hasAttribute(ItemAttribute_t::UNIQUEID)) {
- player->sendCancelMessage(RETURNVALUE_NOTMOVABLE);
- return;
- }
-
const Position &playerPos = player->getPosition();
auto cylinderTile = fromCylinder->getTile();
const Position &mapFromPos = cylinderTile ? cylinderTile->getPosition() : item->getPosition();
@@ -1519,9 +1532,14 @@ void Game::playerMoveItem(std::shared_ptr player, const Position &fromPo
// need to walk to the item first before using it
stdext::arraylist listDir(128);
if (player->getPathTo(item->getPosition(), listDir, 0, 1, true, true)) {
- g_dispatcher().addEvent(std::bind(&Game::playerAutoWalk, this, player->getID(), listDir.data()), "Game::playerAutoWalk");
+ g_dispatcher().addEvent([this, playerId = player->getID(), listDir = listDir.data()] { playerAutoWalk(playerId, listDir); }, "Game::playerAutoWalk");
- std::shared_ptr task = createPlayerTask(400, std::bind(&Game::playerMoveItemByPlayerID, this, player->getID(), fromPos, itemId, fromStackPos, toPos, count), "Game::playerMoveItemByPlayerID");
+ std::shared_ptr task = createPlayerTask(
+ 400, [this, playerId = player->getID(), fromPos, itemId, fromStackPos, toPos, count] {
+ playerMoveItemByPlayerID(playerId, fromPos, itemId, fromStackPos, toPos, count);
+ },
+ "Game::playerMoveItemByPlayerID"
+ );
player->setNextWalkActionTask(task);
} else {
player->sendCancelMessage(RETURNVALUE_THEREISNOWAY);
@@ -1576,9 +1594,14 @@ void Game::playerMoveItem(std::shared_ptr player, const Position &fromPo
stdext::arraylist listDir(128);
if (player->getPathTo(walkPos, listDir, 0, 0, true, true)) {
- g_dispatcher().addEvent(std::bind(&Game::playerAutoWalk, this, player->getID(), listDir.data()), "Game::playerAutoWalk");
-
- std::shared_ptr task = createPlayerTask(400, std::bind(&Game::playerMoveItemByPlayerID, this, player->getID(), itemPos, itemId, itemStackPos, toPos, count), "Game::playerMoveItemByPlayerID");
+ g_dispatcher().addEvent([this, playerId = player->getID(), listDir = listDir.data()] { playerAutoWalk(playerId, listDir); }, "Game::playerAutoWalk");
+
+ std::shared_ptr task = createPlayerTask(
+ 400, [this, playerId = player->getID(), itemPos, itemId, itemStackPos, toPos, count] {
+ playerMoveItemByPlayerID(playerId, itemPos, itemId, itemStackPos, toPos, count);
+ },
+ "Game::playerMoveItemByPlayerID"
+ );
player->setNextWalkActionTask(task);
} else {
player->sendCancelMessage(RETURNVALUE_THEREISNOWAY);
@@ -1624,6 +1647,16 @@ void Game::playerMoveItem(std::shared_ptr player, const Position &fromPo
}
}
+ if (isTryingToStow(toPos, toCylinder)) {
+ player->stowItem(item, count, false);
+ return;
+ }
+
+ if (!item->isPushable() || item->hasAttribute(ItemAttribute_t::UNIQUEID)) {
+ player->sendCancelMessage(RETURNVALUE_NOTMOVABLE);
+ return;
+ }
+
ReturnValue ret = internalMoveItem(fromCylinder, toCylinder, toIndex, item, count, nullptr, 0, player);
if (ret != RETURNVALUE_NOERROR) {
player->sendCancelMessage(ret);
@@ -2583,12 +2616,10 @@ std::shared_ptr
- Game::transformItem(std::shared_ptr
- item, uint16_t n
auto decaying = item->getDecaying();
// If the item is decaying, we need to transform it to the new item
- if (decaying > DECAYING_FALSE && item->getDuration() <= 1) {
+ if (decaying > DECAYING_FALSE && item->getDuration() <= 1 && newType.decayTo) {
g_logger().debug("Decay duration old type {}, transformEquipTo {}, transformDeEquipTo {}", curType.decayTo, curType.transformEquipTo, curType.transformDeEquipTo);
- g_logger().debug("Decay duration new type, decayTo {}, transformEquipTo {}, transformDeEquipTo {}", newType.decayTo, newType.transformEquipTo, newType.transformDeEquipTo);
- if (newType.decayTo) {
- itemId = newType.decayTo;
- }
+ g_logger().debug("Decay duration new type decayTo {}, transformEquipTo {}, transformDeEquipTo {}", newType.decayTo, newType.transformEquipTo, newType.transformDeEquipTo);
+ itemId = newType.decayTo;
} else if (curType.id != newType.id) {
if (newType.group != curType.group) {
item->setDefaultSubtype();
@@ -3484,9 +3515,11 @@ void Game::playerUseItemEx(uint32_t playerId, const Position &fromPos, uint8_t f
stdext::arraylist listDir(128);
if (player->getPathTo(walkToPos, listDir, 0, 1, true, true)) {
- g_dispatcher().addEvent(std::bind(&Game::playerAutoWalk, this, player->getID(), listDir.data()), "Game::playerAutoWalk");
+ g_dispatcher().addEvent([this, playerId = player->getID(), listDir = listDir.data()] { playerAutoWalk(playerId, listDir); }, "Game::playerAutoWalk");
- std::shared_ptr task = createPlayerTask(400, std::bind(&Game::playerUseItemEx, this, playerId, itemPos, itemStackPos, fromItemId, toPos, toStackPos, toItemId), "Game::playerUseItemEx");
+ std::shared_ptr task = createPlayerTask(
+ 400, [this, playerId, itemPos, itemStackPos, fromItemId, toPos, toStackPos, toItemId] { playerUseItemEx(playerId, itemPos, itemStackPos, fromItemId, toPos, toStackPos, toItemId); }, "Game::playerUseItemEx"
+ );
if (it.isRune() || it.type == ITEM_TYPE_POTION) {
player->setNextPotionActionTask(task);
} else {
@@ -3512,7 +3545,9 @@ void Game::playerUseItemEx(uint32_t playerId, const Position &fromPos, uint8_t f
if (it.isRune() || it.type == ITEM_TYPE_POTION) {
delay = player->getNextPotionActionTime();
}
- std::shared_ptr task = createPlayerTask(delay, std::bind(&Game::playerUseItemEx, this, playerId, fromPos, fromStackPos, fromItemId, toPos, toStackPos, toItemId), "Game::playerUseItemEx");
+ std::shared_ptr task = createPlayerTask(
+ delay, [this, playerId, fromPos, fromStackPos, fromItemId, toPos, toStackPos, toItemId] { playerUseItemEx(playerId, fromPos, fromStackPos, fromItemId, toPos, toStackPos, toItemId); }, "Game::playerUseItemEx"
+ );
if (it.isRune() || it.type == ITEM_TYPE_POTION) {
player->setNextPotionActionTask(task);
} else {
@@ -3594,9 +3629,11 @@ void Game::playerUseItem(uint32_t playerId, const Position &pos, uint8_t stackPo
if (ret == RETURNVALUE_TOOFARAWAY) {
stdext::arraylist listDir(128);
if (player->getPathTo(pos, listDir, 0, 1, true, true)) {
- g_dispatcher().addEvent(std::bind(&Game::playerAutoWalk, this, player->getID(), listDir.data()), "Game::playerAutoWalk");
+ g_dispatcher().addEvent([this, playerId = player->getID(), listDir = listDir.data()] { playerAutoWalk(playerId, listDir); }, "Game::playerAutoWalk");
- std::shared_ptr task = createPlayerTask(400, std::bind(&Game::playerUseItem, this, playerId, pos, stackPos, index, itemId), "Game::playerUseItem");
+ std::shared_ptr task = createPlayerTask(
+ 400, [this, playerId, pos, stackPos, index, itemId] { playerUseItem(playerId, pos, stackPos, index, itemId); }, "Game::playerUseItem"
+ );
if (it.isRune() || it.type == ITEM_TYPE_POTION) {
player->setNextPotionActionTask(task);
} else {
@@ -3622,7 +3659,9 @@ void Game::playerUseItem(uint32_t playerId, const Position &pos, uint8_t stackPo
if (it.isRune() || it.type == ITEM_TYPE_POTION) {
delay = player->getNextPotionActionTime();
}
- std::shared_ptr task = createPlayerTask(delay, std::bind(&Game::playerUseItem, this, playerId, pos, stackPos, index, itemId), "Game::playerUseItem");
+ std::shared_ptr task = createPlayerTask(
+ delay, [this, playerId, pos, stackPos, index, itemId] { playerUseItem(playerId, pos, stackPos, index, itemId); }, "Game::playerUseItem"
+ );
if (it.isRune() || it.type == ITEM_TYPE_POTION) {
player->setNextPotionActionTask(task);
} else {
@@ -3734,9 +3773,14 @@ void Game::playerUseWithCreature(uint32_t playerId, const Position &fromPos, uin
stdext::arraylist listDir(128);
if (player->getPathTo(walkToPos, listDir, 0, 1, true, true)) {
- g_dispatcher().addEvent(std::bind(&Game::playerAutoWalk, this, player->getID(), listDir.data()), "Game::playerAutoWalk");
-
- std::shared_ptr task = createPlayerTask(400, std::bind(&Game::playerUseWithCreature, this, playerId, itemPos, itemStackPos, creatureId, itemId), "Game::playerUseWithCreature");
+ g_dispatcher().addEvent([this, playerId = player->getID(), listDir = listDir.data()] { playerAutoWalk(playerId, listDir); }, "Game::playerAutoWalk");
+
+ std::shared_ptr task = createPlayerTask(
+ 400, [this, playerId, itemPos, itemStackPos, creatureId, itemId] {
+ playerUseWithCreature(playerId, itemPos, itemStackPos, creatureId, itemId);
+ },
+ "Game::playerUseWithCreature"
+ );
if (it.isRune() || it.type == ITEM_TYPE_POTION) {
player->setNextPotionActionTask(task);
} else {
@@ -3762,7 +3806,9 @@ void Game::playerUseWithCreature(uint32_t playerId, const Position &fromPos, uin
if (it.isRune() || it.type == ITEM_TYPE_POTION) {
delay = player->getNextPotionActionTime();
}
- std::shared_ptr task = createPlayerTask(delay, std::bind(&Game::playerUseWithCreature, this, playerId, fromPos, fromStackPos, creatureId, itemId), "Game::playerUseWithCreature");
+ std::shared_ptr task = createPlayerTask(
+ delay, [this, playerId, fromPos, fromStackPos, creatureId, itemId] { playerUseWithCreature(playerId, fromPos, fromStackPos, creatureId, itemId); }, "Game::playerUseWithCreature"
+ );
if (it.isRune() || it.type == ITEM_TYPE_POTION) {
player->setNextPotionActionTask(task);
@@ -3888,9 +3934,14 @@ void Game::playerRotateItem(uint32_t playerId, const Position &pos, uint8_t stac
if (pos.x != 0xFFFF && !Position::areInRange<1, 1, 0>(pos, player->getPosition())) {
stdext::arraylist listDir(128);
if (player->getPathTo(pos, listDir, 0, 1, true, true)) {
- g_dispatcher().addEvent(std::bind(&Game::playerAutoWalk, this, player->getID(), listDir.data()), "Game::playerAutoWalk");
+ g_dispatcher().addEvent([this, playerId = player->getID(), listDir = listDir.data()] { playerAutoWalk(playerId, listDir); }, "Game::playerAutoWalk");
- std::shared_ptr task = createPlayerTask(400, std::bind(&Game::playerRotateItem, this, playerId, pos, stackPos, itemId), "Game::playerRotateItem");
+ std::shared_ptr task = createPlayerTask(
+ 400, [this, playerId, pos, stackPos, itemId] {
+ playerRotateItem(playerId, pos, stackPos, itemId);
+ },
+ "Game::playerRotateItem"
+ );
player->setNextWalkActionTask(task);
} else {
player->sendCancelMessage(RETURNVALUE_THEREISNOWAY);
@@ -3939,12 +3990,16 @@ void Game::playerConfigureShowOffSocket(uint32_t playerId, const Position &pos,
if (!Position::areInRange<1, 1, 0>(pos, player->getPosition())) {
stdext::arraylist listDir(128);
if (player->getPathTo(pos, listDir, 0, 1, true, false)) {
- g_dispatcher().addEvent(std::bind(&Game::playerAutoWalk, this, player->getID(), listDir.data()), "Game::playerAutoWalk");
+ g_dispatcher().addEvent([this, playerId = player->getID(), listDir = listDir.data()] { playerAutoWalk(playerId, listDir); }, "Game::playerAutoWalk");
std::shared_ptr task;
if (isPodiumOfRenown) {
- task = createPlayerTask(400, std::bind_front(&Player::sendPodiumWindow, player, item, pos, itemId, stackPos), "Game::playerConfigureShowOffSocket");
+ task = createPlayerTask(
+ 400, [player, item, pos, itemId, stackPos] { player->sendPodiumWindow(item, pos, itemId, stackPos); }, "Game::playerConfigureShowOffSocket"
+ );
} else {
- task = createPlayerTask(400, std::bind_front(&Player::sendMonsterPodiumWindow, player, item, pos, itemId, stackPos), "Game::playerConfigureShowOffSocket");
+ task = createPlayerTask(
+ 400, [player, item, pos, itemId, stackPos] { player->sendMonsterPodiumWindow(item, pos, itemId, stackPos); }, "Game::playerConfigureShowOffSocket"
+ );
}
player->setNextWalkActionTask(task);
} else {
@@ -3996,8 +4051,10 @@ void Game::playerSetShowOffSocket(uint32_t playerId, Outfit_t &outfit, const Pos
if (!Position::areInRange<1, 1, 0>(pos, player->getPosition())) {
stdext::arraylist listDir(128);
if (player->getPathTo(pos, listDir, 0, 1, true, false)) {
- g_dispatcher().addEvent(std::bind(&Game::playerAutoWalk, this, player->getID(), listDir.data()), "Game::playerAutoWalk");
- std::shared_ptr task = createPlayerTask(400, std::bind(&Game::playerBrowseField, this, playerId, pos), "Game::playerBrowseField");
+ g_dispatcher().addEvent([this, playerId = player->getID(), listDir = listDir.data()] { playerAutoWalk(playerId, listDir); }, "Game::playerAutoWalk");
+ std::shared_ptr task = createPlayerTask(
+ 400, [this, playerId, pos] { playerBrowseField(playerId, pos); }, "Game::playerBrowseField"
+ );
player->setNextWalkActionTask(task);
} else {
player->sendCancelMessage(RETURNVALUE_THEREISNOWAY);
@@ -4135,9 +4192,11 @@ void Game::playerWrapableItem(uint32_t playerId, const Position &pos, uint8_t st
if (pos.x != 0xFFFF && !Position::areInRange<1, 1, 0>(pos, player->getPosition())) {
stdext::arraylist listDir(128);
if (player->getPathTo(pos, listDir, 0, 1, true, true)) {
- g_dispatcher().addEvent(std::bind(&Game::playerAutoWalk, this, player->getID(), listDir.data()), "Game::playerAutoWalk");
+ g_dispatcher().addEvent([this, playerId = player->getID(), listDir = listDir.data()] { playerAutoWalk(playerId, listDir); }, "Game::playerAutoWalk");
- std::shared_ptr task = createPlayerTask(400, std::bind(&Game::playerWrapableItem, this, playerId, pos, stackPos, itemId), "Game::playerWrapableItem");
+ std::shared_ptr task = createPlayerTask(
+ 400, [this, playerId, pos, stackPos, itemId] { playerWrapableItem(playerId, pos, stackPos, itemId); }, "Game::playerWrapableItem"
+ );
player->setNextWalkActionTask(task);
} else {
player->sendCancelMessage(RETURNVALUE_THEREISNOWAY);
@@ -4314,8 +4373,10 @@ void Game::playerBrowseField(uint32_t playerId, const Position &pos) {
if (!Position::areInRange<1, 1>(playerPos, pos)) {
stdext::arraylist listDir(128);
if (player->getPathTo(pos, listDir, 0, 1, true, true)) {
- g_dispatcher().addEvent(std::bind(&Game::playerAutoWalk, this, player->getID(), listDir.data()), "Game::playerAutoWalk");
- std::shared_ptr task = createPlayerTask(400, std::bind(&Game::playerBrowseField, this, playerId, pos), "Game::playerBrowseField");
+ g_dispatcher().addEvent([this, playerId = player->getID(), listDir = listDir.data()] { playerAutoWalk(playerId, listDir); }, "Game::playerAutoWalk");
+ std::shared_ptr task = createPlayerTask(
+ 400, [this, playerId, pos] { playerBrowseField(playerId, pos); }, "Game::playerBrowseField"
+ );
player->setNextWalkActionTask(task);
} else {
player->sendCancelMessage(RETURNVALUE_THEREISNOWAY);
@@ -4575,9 +4636,11 @@ void Game::playerRequestTrade(uint32_t playerId, const Position &pos, uint8_t st
if (!Position::areInRange<1, 1>(tradeItemPosition, playerPosition)) {
stdext::arraylist listDir(128);
if (player->getPathTo(pos, listDir, 0, 1, true, true)) {
- g_dispatcher().addEvent(std::bind(&Game::playerAutoWalk, this, player->getID(), listDir.data()), "Game::playerAutoWalk");
+ g_dispatcher().addEvent([this, playerId = player->getID(), listDir = listDir.data()] { playerAutoWalk(playerId, listDir); }, "Game::playerAutoWalk");
- std::shared_ptr task = createPlayerTask(400, std::bind(&Game::playerRequestTrade, this, playerId, pos, stackPos, tradePlayerId, itemId), "Game::playerRequestTrade");
+ std::shared_ptr task = createPlayerTask(
+ 400, [this, playerId, pos, stackPos, tradePlayerId, itemId] { playerRequestTrade(playerId, pos, stackPos, tradePlayerId, itemId); }, "Game::playerRequestTrade"
+ );
player->setNextWalkActionTask(task);
} else {
player->sendCancelMessage(RETURNVALUE_THEREISNOWAY);
@@ -5120,7 +5183,12 @@ void Game::playerQuickLoot(uint32_t playerId, const Position &pos, uint16_t item
if (!autoLoot && !player->canDoAction()) {
uint32_t delay = player->getNextActionTime();
- std::shared_ptr task = createPlayerTask(delay, std::bind(&Game::playerQuickLoot, this, player->getID(), pos, itemId, stackPos, defaultItem, lootAllCorpses, autoLoot), "Game::playerQuickLoot");
+ std::shared_ptr task = createPlayerTask(
+ delay, [this, playerId = player->getID(), pos, itemId, stackPos, defaultItem, lootAllCorpses, autoLoot] {
+ playerQuickLoot(playerId, pos, itemId, stackPos, defaultItem, lootAllCorpses, autoLoot);
+ },
+ "Game::playerQuickLoot"
+ );
player->setNextActionTask(task);
return;
}
@@ -5130,8 +5198,13 @@ void Game::playerQuickLoot(uint32_t playerId, const Position &pos, uint16_t item
// need to walk to the corpse first before looting it
stdext::arraylist listDir(128);
if (player->getPathTo(pos, listDir, 0, 1, true, true)) {
- g_dispatcher().addEvent(std::bind(&Game::playerAutoWalk, this, player->getID(), listDir.data()), "Game::playerAutoWalk");
- std::shared_ptr task = createPlayerTask(0, std::bind(&Game::playerQuickLoot, this, player->getID(), pos, itemId, stackPos, defaultItem, lootAllCorpses, autoLoot), "Game::playerQuickLoot");
+ g_dispatcher().addEvent([this, playerId = player->getID(), listDir = listDir.data()] { playerAutoWalk(playerId, listDir); }, "Game::playerAutoWalk");
+ std::shared_ptr task = createPlayerTask(
+ 0, [this, playerId = player->getID(), pos, itemId, stackPos, defaultItem, lootAllCorpses, autoLoot] {
+ playerQuickLoot(playerId, pos, itemId, stackPos, defaultItem, lootAllCorpses, autoLoot);
+ },
+ "Game::playerQuickLoot"
+ );
player->setNextWalkActionTask(task);
} else {
player->sendCancelMessage(RETURNVALUE_THEREISNOWAY);
@@ -5494,7 +5567,7 @@ void Game::playerSetAttackedCreature(uint32_t playerId, uint32_t creatureId) {
}
player->setAttackedCreature(attackCreature);
- g_dispatcher().addEvent(std::bind(&Game::updateCreatureWalk, this, player->getID()), "Game::updateCreatureWalk");
+ g_dispatcher().addEvent([this, plyerId = player->getID()] { updateCreatureWalk(plyerId); }, "Game::updateCreatureWalk");
}
void Game::playerFollowCreature(uint32_t playerId, uint32_t creatureId) {
@@ -5504,7 +5577,7 @@ void Game::playerFollowCreature(uint32_t playerId, uint32_t creatureId) {
}
player->setAttackedCreature(nullptr);
- g_dispatcher().addEvent(std::bind(&Game::updateCreatureWalk, this, player->getID()), "Game::updateCreatureWalk");
+ g_dispatcher().addEvent([this, plyerId = player->getID()] { updateCreatureWalk(plyerId); }, "Game::updateCreatureWalk");
player->setFollowCreature(getCreatureByID(creatureId));
}
@@ -6252,7 +6325,6 @@ bool Game::combatBlockHit(CombatDamage &damage, std::shared_ptr attack
std::shared_ptr targetPlayer = target->getPlayer();
if (damage.primary.type != COMBAT_NONE) {
-
damage.primary.value = -damage.primary.value;
// Damage healing primary
if (attacker) {
@@ -9330,8 +9402,10 @@ void Game::playerSetMonsterPodium(uint32_t playerId, uint32_t monsterRaceId, con
if (!Position::areInRange<1, 1, 0>(pos, player->getPosition())) {
if (stdext::arraylist listDir(128);
player->getPathTo(pos, listDir, 0, 1, true, false)) {
- g_dispatcher().addEvent(std::bind_front(&Game::playerAutoWalk, this, player->getID(), listDir.data()), "Game::playerAutoWalk");
- std::shared_ptr task = createPlayerTask(400, std::bind_front(&Game::playerBrowseField, this, playerId, pos), "Game::playerBrowseField");
+ g_dispatcher().addEvent([this, playerId = player->getID(), listDir = listDir.data()] { playerAutoWalk(playerId, listDir); }, "Game::playerAutoWalk");
+ std::shared_ptr task = createPlayerTask(
+ 400, [this, playerId, pos] { playerBrowseField(playerId, pos); }, "Game::playerBrowseField"
+ );
player->setNextWalkActionTask(task);
} else {
player->sendCancelMessage(RETURNVALUE_THEREISNOWAY);
@@ -9428,9 +9502,13 @@ void Game::playerRotatePodium(uint32_t playerId, const Position &pos, uint8_t st
if (pos.x != 0xFFFF && !Position::areInRange<1, 1, 0>(pos, player->getPosition())) {
if (stdext::arraylist listDir(128);
player->getPathTo(pos, listDir, 0, 1, true, true)) {
- g_dispatcher().addEvent(std::bind_front(&Game::playerAutoWalk, this, player->getID(), listDir.data()), "Game::playerAutoWalk");
-
- std::shared_ptr task = createPlayerTask(400, std::bind_front(&Game::playerRotatePodium, this, playerId, pos, stackPos, itemId), "Game::playerRotatePodium");
+ g_dispatcher().addEvent([this, playerId = player->getID(), listDir = listDir.data()] { playerAutoWalk(playerId, listDir); }, "Game::playerAutoWalk");
+ std::shared_ptr task = createPlayerTask(
+ 400, [this, playerId, pos, stackPos, itemId] {
+ playerRotatePodium(playerId, pos, stackPos, itemId);
+ },
+ "Game::playerRotatePodium"
+ );
player->setNextWalkActionTask(task);
} else {
player->sendCancelMessage(RETURNVALUE_THEREISNOWAY);
@@ -9611,14 +9689,14 @@ void Game::updatePlayerSaleItems(uint32_t playerId) {
void Game::addPlayer(std::shared_ptr player) {
const std::string &lowercase_name = asLowerCaseString(player->getName());
mappedPlayerNames[lowercase_name] = player;
- wildcardTree.insert(lowercase_name);
+ wildcardTree->insert(lowercase_name);
players[player->getID()] = player;
}
void Game::removePlayer(std::shared_ptr player) {
const std::string &lowercase_name = asLowerCaseString(player->getName());
mappedPlayerNames.erase(lowercase_name);
- wildcardTree.remove(lowercase_name);
+ wildcardTree->remove(lowercase_name);
players.erase(player->getID());
}
@@ -9947,7 +10025,7 @@ uint32_t Game::makeFiendishMonster(uint32_t forgeableMonsterId /* = 0*/, bool cr
auto schedulerTask = createPlayerTask(
finalTime,
- std::bind_front(&Game::updateFiendishMonsterStatus, this, monster->getID(), monster->getName()),
+ [this, monster] { updateFiendishMonsterStatus(monster->getID(), monster->getName()); },
"Game::updateFiendishMonsterStatus"
);
forgeMonsterEventIds[monster->getID()] = g_dispatcher().scheduleEvent(schedulerTask);
@@ -9986,7 +10064,9 @@ bool Game::removeInfluencedMonster(uint32_t id, bool create /* = false*/) {
influencedMonsters.erase(find);
if (create) {
- g_dispatcher().scheduleEvent(200 * 1000, std::bind_front(&Game::makeInfluencedMonster, this), "Game::makeInfluencedMonster");
+ g_dispatcher().scheduleEvent(
+ 200 * 1000, [this] { makeInfluencedMonster(); }, "Game::makeInfluencedMonster"
+ );
}
} else {
g_logger().warn("[Game::removeInfluencedMonster] - Failed to remove a Influenced Monster, error code: monster id not exist in the influenced monsters map");
@@ -10002,7 +10082,9 @@ bool Game::removeFiendishMonster(uint32_t id, bool create /* = true*/) {
checkForgeEventId(id);
if (create) {
- g_dispatcher().scheduleEvent(300 * 1000, std::bind_front(&Game::makeFiendishMonster, this, 0, false), "Game::makeFiendishMonster");
+ g_dispatcher().scheduleEvent(
+ 300 * 1000, [this] { makeFiendishMonster(0, false); }, "Game::makeFiendishMonster"
+ );
}
} else {
g_logger().warn("[Game::removeFiendishMonster] - Failed to remove a Fiendish Monster, error code: monster id not exist in the fiendish monsters map");
@@ -10200,7 +10282,9 @@ void Game::playerCheckActivity(const std::string &playerName, int interval) {
}
}
- g_dispatcher().scheduleEvent(1000, std::bind(&Game::playerCheckActivity, this, playerName, interval), "Game::playerCheckActivity");
+ g_dispatcher().scheduleEvent(
+ 1000, [this, playerName, interval] { playerCheckActivity(playerName, interval); }, "Game::playerCheckActivity"
+ );
}
void Game::playerRewardChestCollect(uint32_t playerId, const Position &pos, uint16_t itemId, uint8_t stackPos, uint32_t maxMoveItems /* = 0*/) {
@@ -10221,8 +10305,11 @@ void Game::playerRewardChestCollect(uint32_t playerId, const Position &pos, uint
return;
}
- if (auto function = std::bind(&Game::playerRewardChestCollect, this, player->getID(), pos, itemId, stackPos, maxMoveItems);
- player->canAutoWalk(item->getPosition(), function)) {
+ const auto &function = [this, playerId = player->getID(), pos, itemId, stackPos, maxMoveItems] {
+ playerRewardChestCollect(playerId, pos, itemId, stackPos, maxMoveItems);
+ };
+
+ if (player->canAutoWalk(item->getPosition(), function)) {
return;
}
diff --git a/src/game/game.hpp b/src/game/game.hpp
index d70263c1775..708aa4b1782 100644
--- a/src/game/game.hpp
+++ b/src/game/game.hpp
@@ -840,7 +840,7 @@ class Game {
size_t lastBucket = 0;
size_t lastImbuedBucket = 0;
- WildcardTreeNode wildcardTree { false };
+ std::shared_ptr wildcardTree;
std::map> npcs;
std::map> monsters;
diff --git a/src/io/iologindata.cpp b/src/io/iologindata.cpp
index 7e113ef901e..4c6b95dc32e 100644
--- a/src/io/iologindata.cpp
+++ b/src/io/iologindata.cpp
@@ -172,6 +172,9 @@ bool IOLoginData::loadPlayer(std::shared_ptr player, DBResult_ptr result
// Load task hunting class
IOLoginDataLoad::loadPlayerTaskHuntingClass(player, result);
+ // Load instant spells list
+ IOLoginDataLoad::loadPlayerInstantSpellList(player, result);
+
if (disableIrrelevantInfo) {
return true;
}
diff --git a/src/items/bed.cpp b/src/items/bed.cpp
index 4ce4a1e0edd..d093dcc5fd9 100644
--- a/src/items/bed.cpp
+++ b/src/items/bed.cpp
@@ -165,7 +165,9 @@ bool BedItem::sleep(std::shared_ptr player) {
g_game().addMagicEffect(player->getPosition(), CONST_ME_SLEEP);
// logout player after he sees himself walk onto the bed and it change id
- g_dispatcher().scheduleEvent(SCHEDULER_MINTICKS, std::bind(&ProtocolGame::logout, player->client, false, false), "ProtocolGame::logout");
+ g_dispatcher().scheduleEvent(
+ SCHEDULER_MINTICKS, [client = player->client] { client->logout(false, false); }, "ProtocolGame::logout"
+ );
// change self and partner's appearance
updateAppearance(player);
diff --git a/src/items/decay/decay.cpp b/src/items/decay/decay.cpp
index 27ae7b6b485..848acffbf68 100644
--- a/src/items/decay/decay.cpp
+++ b/src/items/decay/decay.cpp
@@ -47,11 +47,15 @@ void Decay::startDecay(std::shared_ptr
- item) {
int64_t timestamp = OTSYS_TIME() + duration;
if (decayMap.empty()) {
- eventId = g_dispatcher().scheduleEvent(std::max(SCHEDULER_MINTICKS, duration), std::bind(&Decay::checkDecay, this), "Decay::checkDecay");
+ eventId = g_dispatcher().scheduleEvent(
+ std::max(SCHEDULER_MINTICKS, duration), [this] { checkDecay(); }, "Decay::checkDecay"
+ );
} else {
if (timestamp < decayMap.begin()->first) {
g_dispatcher().stopEvent(eventId);
- eventId = g_dispatcher().scheduleEvent(std::max(SCHEDULER_MINTICKS, duration), std::bind(&Decay::checkDecay, this), "Decay::checkDecay");
+ eventId = g_dispatcher().scheduleEvent(
+ std::max(SCHEDULER_MINTICKS, duration), [this] { checkDecay(); }, "Decay::checkDecay"
+ );
}
}
@@ -138,7 +142,9 @@ void Decay::checkDecay() {
}
if (it != end) {
- eventId = g_dispatcher().scheduleEvent(std::max(SCHEDULER_MINTICKS, static_cast(it->first - timestamp)), std::bind(&Decay::checkDecay, this), "Decay::checkDecay");
+ eventId = g_dispatcher().scheduleEvent(
+ std::max(SCHEDULER_MINTICKS, static_cast(it->first - timestamp)), [this] { checkDecay(); }, "Decay::checkDecay"
+ );
}
}
diff --git a/src/lib/CMakeLists.txt b/src/lib/CMakeLists.txt
index 402c6a34a79..55709c59ac3 100644
--- a/src/lib/CMakeLists.txt
+++ b/src/lib/CMakeLists.txt
@@ -1,6 +1,9 @@
target_sources(${PROJECT_NAME}_lib PRIVATE
di/soft_singleton.cpp
logging/log_with_spd_log.cpp
- metrics/metrics.cpp
thread/thread_pool.cpp
)
+
+if(FEATURE_METRICS)
+ target_sources(${PROJECT_NAME}_lib PRIVATE metrics/metrics.cpp)
+endif()
diff --git a/src/lib/metrics/metrics.cpp b/src/lib/metrics/metrics.cpp
index 2a65e9a7d5d..cf11060125a 100644
--- a/src/lib/metrics/metrics.cpp
+++ b/src/lib/metrics/metrics.cpp
@@ -1,3 +1,4 @@
+#ifdef FEATURE_METRICS
/**
* Canary - A free and open-source MMORPG server emulator
* Copyright (©) 2019-2024 OpenTibiaBR
@@ -7,8 +8,8 @@
* Website: https://docs.opentibiabr.com/
*/
-#include "metrics.hpp"
-#include "lib/di/container.hpp"
+ #include "metrics.hpp"
+ #include "lib/di/container.hpp"
using namespace metrics;
@@ -41,7 +42,7 @@ void Metrics::init(Options opts) {
initHistograms();
}
-void Metrics ::initHistograms() {
+void Metrics::initHistograms() {
for (auto name : latencyNames) {
auto instrumentSelector = metrics_sdk::InstrumentSelectorFactory::Create(metrics_sdk::InstrumentType::kHistogram, name, "us");
auto meterSelector = metrics_sdk::MeterSelectorFactory::Create("performance", otelVersion, otelSchema);
@@ -108,3 +109,5 @@ void ScopedLatency::stop() {
auto attrskv = opentelemetry::common::KeyValueIterableView { attrs };
histogram->Record(elapsed, attrskv, context);
}
+
+#endif // FEATURE_METRICS
diff --git a/src/lib/metrics/metrics.hpp b/src/lib/metrics/metrics.hpp
index 0d8c291dfbe..279ea5f91c5 100644
--- a/src/lib/metrics/metrics.hpp
+++ b/src/lib/metrics/metrics.hpp
@@ -9,43 +9,29 @@
#pragma once
-#include "game/scheduling/dispatcher.hpp"
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
+#ifdef FEATURE_METRICS
+ #include "game/scheduling/dispatcher.hpp"
+ #include
+ #include
+ #include
+ #include
+ #include
+ #include
+ #include
+ #include
+ #include
+ #include
+ #include
+ #include
+ #include
+ #include
+ #include
namespace metrics_sdk = opentelemetry::sdk::metrics;
namespace common = opentelemetry::common;
namespace metrics_exporter = opentelemetry::exporter::metrics;
namespace metrics_api = opentelemetry::metrics;
-constexpr std::string_view methodName(const char* s) {
- std::string_view prettyFunction(s);
- size_t bracket = prettyFunction.rfind("(");
- size_t space = prettyFunction.rfind(" ", bracket) + 1;
- return prettyFunction.substr(space, bracket - space);
-}
-
-#if defined(__GNUC__) || defined(__clang__)
- #define __METHOD_NAME__ methodName(__PRETTY_FUNCTION__)
-#elif defined(_MSC_VER)
- #define __METHOD_NAME__ methodName(__FUNCSIG__)
-#else
- #error "Compiler not supported"
-#endif
-
namespace metrics {
using Meter = opentelemetry::nostd::shared_ptr;
@@ -85,12 +71,12 @@ namespace metrics {
bool stopped { false };
};
-#define DEFINE_LATENCY_CLASS(class_name, histogram_name, category) \
- class class_name##_latency final : public ScopedLatency { \
- public: \
- class_name##_latency(std::string_view name) : \
- ScopedLatency(name, histogram_name "_latency", category) { } \
- }
+ #define DEFINE_LATENCY_CLASS(class_name, histogram_name, category) \
+ class class_name##_latency final : public ScopedLatency { \
+ public: \
+ class_name##_latency(std::string_view name) : \
+ ScopedLatency(name, histogram_name "_latency", category) { } \
+ }
DEFINE_LATENCY_CLASS(method, "method", "method");
DEFINE_LATENCY_CLASS(lua, "lua", "scope");
@@ -170,3 +156,70 @@ namespace metrics {
constexpr auto g_metrics
= metrics::Metrics::getInstance;
+
+#else // FEATURE_METRICS
+
+ #include "lib/di/container.hpp"
+
+struct Options {
+ bool enablePrometheusExporter;
+ bool enableOStreamExporter;
+};
+
+class ScopedLatency {
+public:
+ explicit ScopedLatency([[maybe_unused]] std::string_view name, [[maybe_unused]] const std::string &histogramName, [[maybe_unused]] const std::string &scopeKey) {};
+ explicit ScopedLatency([[maybe_unused]] std::string_view name, [[maybe_unused]] std::set &histogram, [[maybe_unused]] const std::map &attrs = {}, [[maybe_unused]] const std::string &context = std::string()) {};
+
+ void stop() {};
+
+ ~ScopedLatency() = default;
+};
+
+namespace metrics {
+ #define DEFINE_LATENCY_CLASS(class_name, histogram_name, category) \
+ class class_name##_latency final : public ScopedLatency { \
+ public: \
+ class_name##_latency(std::string_view name) : \
+ ScopedLatency(name, histogram_name "_latency", category) { } \
+ }
+
+ DEFINE_LATENCY_CLASS(method, "method", "method");
+ DEFINE_LATENCY_CLASS(lua, "lua", "scope");
+ DEFINE_LATENCY_CLASS(query, "query", "truncated_query");
+ DEFINE_LATENCY_CLASS(task, "task", "task");
+ DEFINE_LATENCY_CLASS(lock, "lock", "scope");
+
+ const std::vector latencyNames {
+ "method_latency",
+ "lua_latency",
+ "query_latency",
+ "task_latency",
+ "lock_latency",
+ };
+
+ class Metrics final {
+ public:
+ Metrics() = default;
+ ~Metrics() = default;
+
+ void init([[maybe_unused]] Options opts) {};
+ void initHistograms() {};
+ void shutdown() {};
+
+ static Metrics &getInstance() {
+ return inject();
+ };
+
+ void addCounter([[maybe_unused]] std::string_view name, [[maybe_unused]] double value, [[maybe_unused]] const std::map &attrs = {}) { }
+
+ void addUpDownCounter([[maybe_unused]] std::string_view name, [[maybe_unused]] int value, [[maybe_unused]] const std::map &attrs = {}) { }
+
+ friend class ScopedLatency;
+ };
+}
+
+constexpr auto g_metrics
+ = metrics::Metrics::getInstance;
+
+#endif // FEATURE_METRICS
diff --git a/src/lua/creature/raids.cpp b/src/lua/creature/raids.cpp
index f0d7cecf402..a4500d126ba 100644
--- a/src/lua/creature/raids.cpp
+++ b/src/lua/creature/raids.cpp
@@ -102,7 +102,9 @@ bool Raids::startup() {
setLastRaidEnd(OTSYS_TIME());
- checkRaidsEvent = g_dispatcher().scheduleEvent(CHECK_RAIDS_INTERVAL * 1000, std::bind(&Raids::checkRaids, this), "Raids::checkRaids");
+ checkRaidsEvent = g_dispatcher().scheduleEvent(
+ CHECK_RAIDS_INTERVAL * 1000, [this] { checkRaids(); }, "Raids::checkRaids"
+ );
started = true;
return started;
@@ -134,7 +136,9 @@ void Raids::checkRaids() {
}
}
- checkRaidsEvent = g_dispatcher().scheduleEvent(CHECK_RAIDS_INTERVAL * 1000, std::bind(&Raids::checkRaids, this), "Raids::checkRaids");
+ checkRaidsEvent = g_dispatcher().scheduleEvent(
+ CHECK_RAIDS_INTERVAL * 1000, [this] { checkRaids(); }, "Raids::checkRaids"
+ );
}
void Raids::clear() {
@@ -216,7 +220,9 @@ void Raid::startRaid() {
const auto raidEvent = getNextRaidEvent();
if (raidEvent) {
state = RAIDSTATE_EXECUTING;
- nextEventEvent = g_dispatcher().scheduleEvent(raidEvent->getDelay(), std::bind(&Raid::executeRaidEvent, this, raidEvent), "Raid::executeRaidEvent");
+ nextEventEvent = g_dispatcher().scheduleEvent(
+ raidEvent->getDelay(), [this, raidEvent] { executeRaidEvent(raidEvent); }, "Raid::executeRaidEvent"
+ );
} else {
g_logger().warn("[raids] Raid {} has no events", name);
resetRaid();
@@ -230,7 +236,9 @@ void Raid::executeRaidEvent(const std::shared_ptr raidEvent) {
if (newRaidEvent) {
uint32_t ticks = static_cast(std::max(RAID_MINTICKS, newRaidEvent->getDelay() - raidEvent->getDelay()));
- nextEventEvent = g_dispatcher().scheduleEvent(ticks, std::bind(&Raid::executeRaidEvent, this, newRaidEvent), __FUNCTION__);
+ nextEventEvent = g_dispatcher().scheduleEvent(
+ ticks, [this, newRaidEvent] { executeRaidEvent(newRaidEvent); }, __FUNCTION__
+ );
} else {
resetRaid();
}
diff --git a/src/lua/functions/core/game/global_functions.cpp b/src/lua/functions/core/game/global_functions.cpp
index cbb133211f8..0403e88dd95 100644
--- a/src/lua/functions/core/game/global_functions.cpp
+++ b/src/lua/functions/core/game/global_functions.cpp
@@ -664,7 +664,7 @@ int GlobalFunctions::luaAddEvent(lua_State* L) {
auto &lastTimerEventId = g_luaEnvironment().lastEventTimerId;
eventDesc.eventId = g_dispatcher().scheduleEvent(
delay,
- std::bind(&LuaEnvironment::executeTimerEvent, &g_luaEnvironment(), lastTimerEventId),
+ [lastTimerEventId] { g_luaEnvironment().executeTimerEvent(lastTimerEventId); },
"LuaEnvironment::executeTimerEvent"
);
diff --git a/src/lua/global/globalevent.cpp b/src/lua/global/globalevent.cpp
index 62650b429a9..9626173dc9f 100644
--- a/src/lua/global/globalevent.cpp
+++ b/src/lua/global/globalevent.cpp
@@ -35,7 +35,9 @@ bool GlobalEvents::registerLuaEvent(const std::shared_ptr globalEve
auto result = timerMap.emplace(globalEvent->getName(), globalEvent);
if (result.second) {
if (timerEventId == 0) {
- timerEventId = g_dispatcher().scheduleEvent(SCHEDULER_MINTICKS, std::bind(&GlobalEvents::timer, this), "GlobalEvents::timer");
+ timerEventId = g_dispatcher().scheduleEvent(
+ SCHEDULER_MINTICKS, [this] { timer(); }, "GlobalEvents::timer"
+ );
}
return true;
}
@@ -99,7 +101,9 @@ void GlobalEvents::timer() {
}
if (nextScheduledTime != std::numeric_limits::max()) {
- timerEventId = g_dispatcher().scheduleEvent(std::max(1000, nextScheduledTime * 1000), std::bind(&GlobalEvents::timer, this), __FUNCTION__);
+ timerEventId = g_dispatcher().scheduleEvent(
+ std::max(1000, nextScheduledTime * 1000), [this] { timer(); }, __FUNCTION__
+ );
}
}
@@ -136,7 +140,9 @@ void GlobalEvents::think() {
if (nextScheduledTime != std::numeric_limits::max()) {
auto delay = static_cast(nextScheduledTime);
- thinkEventId = g_dispatcher().scheduleEvent(delay, std::bind(&GlobalEvents::think, this), "GlobalEvents::think");
+ thinkEventId = g_dispatcher().scheduleEvent(
+ delay, [this] { think(); }, "GlobalEvents::think"
+ );
}
}
diff --git a/src/pch.hpp b/src/pch.hpp
index 522411b5621..e69c27016a4 100644
--- a/src/pch.hpp
+++ b/src/pch.hpp
@@ -45,6 +45,7 @@
#include
#include
#include
+#include
// --------------------
// System Includes
@@ -95,9 +96,6 @@ struct fmt::formatter, char>> : formatter<
// GMP
#include
-// JSON
-#include
-
// LUA
#if __has_include("luajit/lua.hpp")
#include
@@ -172,3 +170,18 @@ struct fmt::formatter, char>> : formatter<
#include
#include "lua/global/shared_object.hpp"
+
+constexpr std::string_view methodName(const char* s) {
+ std::string_view prettyFunction(s);
+ size_t bracket = prettyFunction.rfind('(');
+ size_t space = prettyFunction.rfind(' ', bracket) + 1;
+ return prettyFunction.substr(space, bracket - space);
+}
+
+#if defined(__GNUC__) || defined(__clang__)
+ #define __METHOD_NAME__ methodName(__PRETTY_FUNCTION__)
+#elif defined(_MSC_VER)
+ #define __METHOD_NAME__ methodName(__FUNCSIG__)
+#else
+ #error "Compiler not supported"
+#endif
diff --git a/src/server/network/connection/connection.cpp b/src/server/network/connection/connection.cpp
index 41789b88387..cc27eb0e9eb 100644
--- a/src/server/network/connection/connection.cpp
+++ b/src/server/network/connection/connection.cpp
@@ -62,7 +62,7 @@ void Connection::close(bool force) {
connectionState = CONNECTION_STATE_CLOSED;
if (protocol) {
- g_dispatcher().addEvent(std::bind_front(&Protocol::release, protocol), "Protocol::release", std::chrono::milliseconds(CONNECTION_WRITE_TIMEOUT * 1000).count());
+ g_dispatcher().addEvent([protocol = protocol] { protocol->release(); }, "Protocol::release", std::chrono::milliseconds(CONNECTION_WRITE_TIMEOUT * 1000).count());
}
if (messageQueue.empty() || force) {
@@ -98,19 +98,23 @@ void Connection::closeSocket() {
void Connection::accept(Protocol_ptr protocolPtr) {
connectionState = CONNECTION_STATE_IDENTIFYING;
protocol = std::move(protocolPtr);
- g_dispatcher().addEvent(std::bind_front(&Protocol::onConnect, protocol), "Protocol::onConnect", std::chrono::milliseconds(CONNECTION_WRITE_TIMEOUT * 1000).count());
+ g_dispatcher().addEvent([protocol = protocol] { protocol->onConnect(); }, "Protocol::onConnect", std::chrono::milliseconds(CONNECTION_WRITE_TIMEOUT * 1000).count());
acceptInternal(false);
}
void Connection::acceptInternal(bool toggleParseHeader) {
readTimer.expires_from_now(std::chrono::seconds(CONNECTION_READ_TIMEOUT));
- readTimer.async_wait(std::bind(&Connection::handleTimeout, std::weak_ptr(shared_from_this()), std::placeholders::_1));
+ readTimer.async_wait([self = shared_from_this()](const std::error_code &error) { Connection::handleTimeout(std::weak_ptr(self), error); });
try {
- auto readCallback = toggleParseHeader ? std::bind(&Connection::parseHeader, shared_from_this(), std::placeholders::_1)
- : std::bind(&Connection::parseProxyIdentification, shared_from_this(), std::placeholders::_1);
- asio::async_read(socket, asio::buffer(msg.getBuffer(), HEADER_LENGTH), readCallback);
+ asio::async_read(socket, asio::buffer(msg.getBuffer(), HEADER_LENGTH), [self = shared_from_this(), toggleParseHeader](const std::error_code &error, std::size_t N) {
+ if (toggleParseHeader) {
+ self->parseHeader(error);
+ } else {
+ self->parseProxyIdentification(error);
+ }
+ });
} catch (const std::system_error &e) {
g_logger().error("[Connection::acceptInternal] - Exception in async_read: {}", e.what());
close(FORCE_CLOSE);
@@ -143,10 +147,10 @@ void Connection::parseProxyIdentification(const std::error_code &error) {
connectionState = CONNECTION_STATE_READINGS;
try {
readTimer.expires_from_now(std::chrono::seconds(CONNECTION_READ_TIMEOUT));
- readTimer.async_wait(std::bind(&Connection::handleTimeout, std::weak_ptr(shared_from_this()), std::placeholders::_1));
+ readTimer.async_wait([self = shared_from_this()](const std::error_code &error) { Connection::handleTimeout(std::weak_ptr(self), error); });
// Read the remainder of proxy identification
- asio::async_read(socket, asio::buffer(msg.getBuffer(), remainder), std::bind(&Connection::parseProxyIdentification, shared_from_this(), std::placeholders::_1));
+ asio::async_read(socket, asio::buffer(msg.getBuffer(), remainder), [self = shared_from_this()](const std::error_code &error, std::size_t N) { self->parseProxyIdentification(error); });
} catch (const std::system_error &e) {
g_logger().error("Connection::parseProxyIdentification] - error: {}", e.what());
close(FORCE_CLOSE);
@@ -204,11 +208,12 @@ void Connection::parseHeader(const std::error_code &error) {
try {
readTimer.expires_from_now(std::chrono::seconds(CONNECTION_READ_TIMEOUT));
- readTimer.async_wait(std::bind(&Connection::handleTimeout, std::weak_ptr(shared_from_this()), std::placeholders::_1));
+ readTimer.async_wait([self = shared_from_this()](const std::error_code &error) { Connection::handleTimeout(std::weak_ptr(self), error); });
// Read packet content
msg.setLength(size + HEADER_LENGTH);
- asio::async_read(socket, asio::buffer(msg.getBodyBuffer(), size), std::bind(&Connection::parsePacket, shared_from_this(), std::placeholders::_1));
+ // Read the remainder of proxy identification
+ asio::async_read(socket, asio::buffer(msg.getBodyBuffer(), size), [self = shared_from_this()](const std::error_code &error, std::size_t N) { self->parsePacket(error); });
} catch (const std::system_error &e) {
g_logger().error("[Connection::parseHeader] - error: {}", e.what());
close(FORCE_CLOSE);
@@ -270,11 +275,11 @@ void Connection::parsePacket(const std::error_code &error) {
try {
readTimer.expires_from_now(std::chrono::seconds(CONNECTION_READ_TIMEOUT));
- readTimer.async_wait(std::bind(&Connection::handleTimeout, std::weak_ptr(shared_from_this()), std::placeholders::_1));
+ readTimer.async_wait([self = shared_from_this()](const std::error_code &error) { Connection::handleTimeout(std::weak_ptr(self), error); });
if (!skipReadingNextPacket) {
// Wait to the next packet
- asio::async_read(socket, asio::buffer(msg.getBuffer(), HEADER_LENGTH), std::bind(&Connection::parseHeader, shared_from_this(), std::placeholders::_1));
+ asio::async_read(socket, asio::buffer(msg.getBuffer(), HEADER_LENGTH), [self = shared_from_this()](const std::error_code &error, std::size_t N) { self->parseHeader(error); });
}
} catch (const std::system_error &e) {
g_logger().error("[Connection::parsePacket] - error: {}", e.what());
@@ -284,10 +289,10 @@ void Connection::parsePacket(const std::error_code &error) {
void Connection::resumeWork() {
readTimer.expires_from_now(std::chrono::seconds(CONNECTION_READ_TIMEOUT));
- readTimer.async_wait(std::bind(&Connection::handleTimeout, std::weak_ptr(shared_from_this()), std::placeholders::_1));
+ readTimer.async_wait([self = shared_from_this()](const std::error_code &error) { Connection::handleTimeout(std::weak_ptr(self), error); });
try {
- asio::async_read(socket, asio::buffer(msg.getBuffer(), HEADER_LENGTH), std::bind(&Connection::parseHeader, shared_from_this(), std::placeholders::_1));
+ asio::async_read(socket, asio::buffer(msg.getBuffer(), HEADER_LENGTH), [self = shared_from_this()](const std::error_code &error, std::size_t N) { self->parseHeader(error); });
} catch (const std::system_error &e) {
g_logger().error("[Connection::resumeWork] - Exception in async_read: {}", e.what());
close(FORCE_CLOSE);
@@ -306,7 +311,7 @@ void Connection::send(const OutputMessage_ptr &outputMessage) {
if (noPendingWrite) {
if (socket.is_open()) {
try {
- asio::post(socket.get_executor(), std::bind(&Connection::internalWorker, shared_from_this()));
+ asio::post(socket.get_executor(), [self = shared_from_this()] { self->internalWorker(); });
} catch (const std::system_error &e) {
g_logger().error("[Connection::send] - Exception in posting write operation: {}", e.what());
close(FORCE_CLOSE);
@@ -353,10 +358,10 @@ uint32_t Connection::getIP() {
void Connection::internalSend(const OutputMessage_ptr &outputMessage) {
writeTimer.expires_from_now(std::chrono::seconds(CONNECTION_WRITE_TIMEOUT));
- writeTimer.async_wait(std::bind(&Connection::handleTimeout, std::weak_ptr(shared_from_this()), std::placeholders::_1));
+ readTimer.async_wait([self = shared_from_this()](const std::error_code &error) { Connection::handleTimeout(std::weak_ptr(self), error); });
try {
- asio::async_write(socket, asio::buffer(outputMessage->getOutputBuffer(), outputMessage->getLength()), std::bind(&Connection::onWriteOperation, shared_from_this(), std::placeholders::_1));
+ asio::async_write(socket, asio::buffer(outputMessage->getOutputBuffer(), outputMessage->getLength()), [self = shared_from_this()](const std::error_code &error, std::size_t N) { self->onWriteOperation(error); });
} catch (const std::system_error &e) {
g_logger().error("[Connection::internalSend] - Exception in async_write: {}", e.what());
close(FORCE_CLOSE);
diff --git a/src/server/network/message/outputmessage.cpp b/src/server/network/message/outputmessage.cpp
index 6ede36da406..efed7fe8367 100644
--- a/src/server/network/message/outputmessage.cpp
+++ b/src/server/network/message/outputmessage.cpp
@@ -16,8 +16,9 @@
const std::chrono::milliseconds OUTPUTMESSAGE_AUTOSEND_DELAY { 10 };
void OutputMessagePool::scheduleSendAll() {
- auto function = std::bind_front(&OutputMessagePool::sendAll, this);
- g_dispatcher().scheduleEvent(OUTPUTMESSAGE_AUTOSEND_DELAY.count(), function, "OutputMessagePool::sendAll");
+ g_dispatcher().scheduleEvent(
+ OUTPUTMESSAGE_AUTOSEND_DELAY.count(), [this] { sendAll(); }, "OutputMessagePool::sendAll"
+ );
}
void OutputMessagePool::sendAll() {
diff --git a/src/server/network/protocol/protocolgame.cpp b/src/server/network/protocol/protocolgame.cpp
index 5398155067e..0d0d8e79f17 100644
--- a/src/server/network/protocol/protocolgame.cpp
+++ b/src/server/network/protocol/protocolgame.cpp
@@ -248,16 +248,6 @@ ProtocolGame::ProtocolGame(Connection_ptr initConnection) :
version = CLIENT_VERSION;
}
-template
-void ProtocolGame::addGameTask(Callable function, Args &&... args) {
- g_dispatcher().addEvent(std::bind(function, &g_game(), std::forward(args)...), "ProtocolGame::addGameTask");
-}
-
-template
-void ProtocolGame::addGameTaskTimed(uint32_t delay, std::string_view context, Callable function, Args &&... args) {
- g_dispatcher().addEvent(std::bind(function, &g_game(), std::forward(args)...), context, delay);
-}
-
void ProtocolGame::AddItem(NetworkMessage &msg, uint16_t id, uint8_t count, uint8_t tier) {
const ItemType &it = Item::items[id];
@@ -629,7 +619,10 @@ void ProtocolGame::login(const std::string &name, uint32_t accountId, OperatingS
foundPlayer->disconnect();
foundPlayer->isConnecting = true;
- eventConnect = g_dispatcher().scheduleEvent(1000, std::bind(&ProtocolGame::connect, getThis(), foundPlayer->getName(), operatingSystem), "ProtocolGame::connect");
+ eventConnect = g_dispatcher().scheduleEvent(
+ 1000,
+ [self = getThis(), playerName = foundPlayer->getName(), operatingSystem] { self->connect(playerName, operatingSystem); }, "ProtocolGame::connect"
+ );
} else {
connect(foundPlayer->getName(), operatingSystem);
}
@@ -842,11 +835,13 @@ void ProtocolGame::onRecvFirstMessage(NetworkMessage &msg) {
output->addByte(0x14);
output->addString(ss.str(), "ProtocolGame::onRecvFirstMessage - ss.str()");
send(output);
- g_dispatcher().scheduleEvent(1000, std::bind(&ProtocolGame::disconnect, getThis()), "ProtocolGame::disconnect");
+ g_dispatcher().scheduleEvent(
+ 1000, [self = getThis()] { self->disconnect(); }, "ProtocolGame::disconnect"
+ );
return;
}
- g_dispatcher().addEvent(std::bind(&ProtocolGame::login, getThis(), characterName, accountId, operatingSystem), "ProtocolGame::login");
+ g_dispatcher().addEvent([self = getThis(), characterName, accountId, operatingSystem] { self->login(characterName, accountId, operatingSystem); }, "ProtocolGame::login");
}
void ProtocolGame::onConnect() {
@@ -907,20 +902,20 @@ void ProtocolGame::parsePacket(NetworkMessage &msg) {
if (player->isDead() || player->getHealth() <= 0) {
// Check player activity on death screen
if (m_playerDeathTime == 0) {
- addGameTask(&Game::playerCheckActivity, player->getName(), 1000);
+ g_game().playerCheckActivity(player->getName(), 1000);
m_playerDeathTime++;
}
- g_dispatcher().addEvent(std::bind(&ProtocolGame::parsePacketDead, getThis(), recvbyte), "ProtocolGame::parsePacketDead");
+ parsePacketDead(recvbyte);
return;
}
// Modules system
if (player && recvbyte != 0xD3) {
- g_dispatcher().addEvent(std::bind(&Modules::executeOnRecvbyte, &g_modules(), player->getID(), msg, recvbyte), "Modules::executeOnRecvbyte");
+ g_modules().executeOnRecvbyte(player->getID(), msg, recvbyte);
}
- g_dispatcher().addEvent(std::bind(&ProtocolGame::parsePacketFromDispatcher, getThis(), msg, recvbyte), "ProtocolGame::parsePacketFromDispatcher");
+ parsePacketFromDispatcher(msg, recvbyte);
}
void ProtocolGame::parsePacketDead(uint8_t recvbyte) {
@@ -930,7 +925,7 @@ void ProtocolGame::parsePacketDead(uint8_t recvbyte) {
g_game().removePlayerUniqueLogin(player->getName());
}
disconnect();
- g_dispatcher().addEvent(std::bind(&IOLoginData::updateOnlineStatus, player->getGUID(), false), "IOLoginData::updateOnlineStatus");
+ IOLoginData::updateOnlineStatus(player->getGUID(), false);
return;
}
@@ -939,23 +934,27 @@ void ProtocolGame::parsePacketDead(uint8_t recvbyte) {
return;
}
- g_dispatcher().scheduleEvent(100, std::bind(&ProtocolGame::sendPing, getThis()), "ProtocolGame::sendPing");
+ g_dispatcher().scheduleEvent(
+ 100, [self = getThis()] { self->sendPing(); }, "ProtocolGame::sendPing"
+ );
if (!player->spawn()) {
disconnect();
- addGameTask(&Game::removeCreature, player, true);
+ g_game().removeCreature(player, true);
return;
}
- g_dispatcher().addEvent(std::bind(&ProtocolGame::sendAddCreature, getThis(), player, player->getPosition(), 0, false), "ProtocolGame::sendAddCreature");
- g_dispatcher().addEvent(std::bind(&ProtocolGame::addBless, getThis()), "ProtocolGame::addBless");
+ sendAddCreature(player, player->getPosition(), 0, false);
+ addBless();
resetPlayerDeathTime();
return;
}
if (recvbyte == 0x1D) {
// keep the connection alive
- g_dispatcher().scheduleEvent(100, std::bind(&ProtocolGame::sendPingBack, getThis()), "ProtocolGame::sendPingBack");
+ g_dispatcher().scheduleEvent(
+ 100, [self = getThis()] { self->sendPingBack(); }, "ProtocolGame::sendPingBack"
+ );
return;
}
}
@@ -978,13 +977,13 @@ void ProtocolGame::parsePacketFromDispatcher(NetworkMessage msg, uint8_t recvbyt
switch (recvbyte) {
case 0x14:
- g_dispatcher().addEvent(std::bind(&ProtocolGame::logout, getThis(), true, false), "ProtocolGame::logout");
+ logout(true, false);
break;
case 0x1D:
- addGameTask(&Game::playerReceivePingBack, player->getID());
+ g_game().playerReceivePingBack(player->getID());
break;
case 0x1E:
- addGameTask(&Game::playerReceivePing, player->getID());
+ g_game().playerReceivePing(player->getID());
break;
case 0x2a:
parseCyclopediaMonsterTracker(msg);
@@ -1020,43 +1019,43 @@ void ProtocolGame::parsePacketFromDispatcher(NetworkMessage msg, uint8_t recvbyt
parseAutoWalk(msg);
break;
case 0x65:
- addGameTask(&Game::playerMove, player->getID(), DIRECTION_NORTH);
+ g_game().playerMove(player->getID(), DIRECTION_NORTH);
break;
case 0x66:
- addGameTask(&Game::playerMove, player->getID(), DIRECTION_EAST);
+ g_game().playerMove(player->getID(), DIRECTION_EAST);
break;
case 0x67:
- addGameTask(&Game::playerMove, player->getID(), DIRECTION_SOUTH);
+ g_game().playerMove(player->getID(), DIRECTION_SOUTH);
break;
case 0x68:
- addGameTask(&Game::playerMove, player->getID(), DIRECTION_WEST);
+ g_game().playerMove(player->getID(), DIRECTION_WEST);
break;
case 0x69:
- addGameTask(&Game::playerStopAutoWalk, player->getID());
+ g_game().playerStopAutoWalk(player->getID());
break;
case 0x6A:
- addGameTask(&Game::playerMove, player->getID(), DIRECTION_NORTHEAST);
+ g_game().playerMove(player->getID(), DIRECTION_NORTHEAST);
break;
case 0x6B:
- addGameTask(&Game::playerMove, player->getID(), DIRECTION_SOUTHEAST);
+ g_game().playerMove(player->getID(), DIRECTION_SOUTHEAST);
break;
case 0x6C:
- addGameTask(&Game::playerMove, player->getID(), DIRECTION_SOUTHWEST);
+ g_game().playerMove(player->getID(), DIRECTION_SOUTHWEST);
break;
case 0x6D:
- addGameTask(&Game::playerMove, player->getID(), DIRECTION_NORTHWEST);
+ g_game().playerMove(player->getID(), DIRECTION_NORTHWEST);
break;
case 0x6F:
- addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, "Game::playerTurn", &Game::playerTurn, player->getID(), DIRECTION_NORTH);
+ g_game().playerTurn(player->getID(), DIRECTION_NORTH);
break;
case 0x70:
- addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, "Game::playerTurn", &Game::playerTurn, player->getID(), DIRECTION_EAST);
+ g_game().playerTurn(player->getID(), DIRECTION_EAST);
break;
case 0x71:
- addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, "Game::playerTurn", &Game::playerTurn, player->getID(), DIRECTION_SOUTH);
+ g_game().playerTurn(player->getID(), DIRECTION_SOUTH);
break;
case 0x72:
- addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, "Game::playerTurn", &Game::playerTurn, player->getID(), DIRECTION_WEST);
+ g_game().playerTurn(player->getID(), DIRECTION_WEST);
break;
case 0x73:
parseTeleport(msg);
@@ -1077,7 +1076,7 @@ void ProtocolGame::parsePacketFromDispatcher(NetworkMessage msg, uint8_t recvbyt
parsePlayerSellOnShop(msg);
break;
case 0x7C:
- addGameTask(&Game::playerCloseShop, player->getID());
+ g_game().playerCloseShop(player->getID());
break;
case 0x7D:
parseRequestTrade(msg);
@@ -1086,10 +1085,10 @@ void ProtocolGame::parsePacketFromDispatcher(NetworkMessage msg, uint8_t recvbyt
parseLookInTrade(msg);
break;
case 0x7F:
- addGameTask(&Game::playerAcceptTrade, player->getID());
+ g_game().playerAcceptTrade(player->getID());
break;
case 0x80:
- addGameTask(&Game::playerCloseTrade, player->getID());
+ g_game().playerCloseTrade(player->getID());
break;
case 0x82:
parseUseItem(msg);
@@ -1154,7 +1153,7 @@ void ProtocolGame::parsePacketFromDispatcher(NetworkMessage msg, uint8_t recvbyt
parseSay(msg);
break;
case 0x97:
- addGameTask(&Game::playerRequestChannels, player->getID());
+ g_game().playerRequestChannels(player->getID());
break;
case 0x98:
parseOpenChannel(msg);
@@ -1166,7 +1165,7 @@ void ProtocolGame::parsePacketFromDispatcher(NetworkMessage msg, uint8_t recvbyt
parseOpenPrivateChannel(msg);
break;
case 0x9E:
- addGameTask(&Game::playerCloseNpcChannel, player->getID());
+ g_game().playerCloseNpcChannel(player->getID());
break;
case 0x9F:
parseSetMonsterPodium(msg);
@@ -1193,13 +1192,13 @@ void ProtocolGame::parsePacketFromDispatcher(NetworkMessage msg, uint8_t recvbyt
parsePassPartyLeadership(msg);
break;
case 0xA7:
- addGameTask(&Game::playerLeaveParty, player->getID());
+ g_game().playerLeaveParty(player->getID());
break;
case 0xA8:
parseEnableSharedPartyExperience(msg);
break;
case 0xAA:
- addGameTask(&Game::playerCreatePrivateChannel, player->getID());
+ g_game().playerCreatePrivateChannel(player->getID());
break;
case 0xAB:
parseChannelInvite(msg);
@@ -1223,7 +1222,7 @@ void ProtocolGame::parsePacketFromDispatcher(NetworkMessage msg, uint8_t recvbyt
parseTaskHuntingAction(msg);
break;
case 0xBE:
- addGameTask(&Game::playerCancelAttackAndFollow, player->getID());
+ g_game().playerCancelAttackAndFollow(player->getID());
break;
case 0xBF:
parseForgeEnter(msg);
@@ -1246,11 +1245,10 @@ void ProtocolGame::parsePacketFromDispatcher(NetworkMessage msg, uint8_t recvbyt
parseInspectionObject(msg);
break;
case 0xD2:
- addGameTask(&Game::playerRequestOutfit, player->getID());
+ g_game().playerRequestOutfit(player->getID());
break;
- // g_dispatcher().addEvent(std::bind(&Modules::executeOnRecvbyte, g_modules, player, msg, recvbyte));
case 0xD3:
- g_dispatcher().addEvent(std::bind(&ProtocolGame::parseSetOutfit, getThis(), msg), "ProtocolGame::parseSetOutfit");
+ parseSetOutfit(msg);
break;
case 0xD4:
parseToggleMount(msg);
@@ -1309,7 +1307,7 @@ void ProtocolGame::parsePacketFromDispatcher(NetworkMessage msg, uint8_t recvbyt
// Premium coins transfer
// case 0xEF: parseCoinTransfer(msg); break;
case 0xF0:
- addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, "Game::playerShowQuestLog", &Game::playerShowQuestLog, player->getID());
+ g_game().playerShowQuestLog(player->getID());
break;
case 0xF1:
parseQuestLine(msg);
@@ -1360,7 +1358,7 @@ void ProtocolGame::parseHotkeyEquip(NetworkMessage &msg) {
uint16_t itemId = msg.get();
uint8_t tier = msg.get();
- addGameTask(&Game::playerEquipItem, player->getID(), itemId, Item::items[itemId].upgradeClassification > 0, tier);
+ g_game().playerEquipItem(player->getID(), itemId, Item::items[itemId].upgradeClassification > 0, tier);
}
void ProtocolGame::GetTileDescription(std::shared_ptr tile, NetworkMessage &msg) {
@@ -1563,27 +1561,27 @@ bool ProtocolGame::canSee(int32_t x, int32_t y, int32_t z) const {
// Parse methods
void ProtocolGame::parseChannelInvite(NetworkMessage &msg) {
const std::string name = msg.getString();
- addGameTask(&Game::playerChannelInvite, player->getID(), name);
+ g_game().playerChannelInvite(player->getID(), name);
}
void ProtocolGame::parseChannelExclude(NetworkMessage &msg) {
const std::string name = msg.getString();
- addGameTask(&Game::playerChannelExclude, player->getID(), name);
+ g_game().playerChannelExclude(player->getID(), name);
}
void ProtocolGame::parseOpenChannel(NetworkMessage &msg) {
uint16_t channelId = msg.get();
- addGameTask(&Game::playerOpenChannel, player->getID(), channelId);
+ g_game().playerOpenChannel(player->getID(), channelId);
}
void ProtocolGame::parseCloseChannel(NetworkMessage &msg) {
uint16_t channelId = msg.get();
- addGameTask(&Game::playerCloseChannel, player->getID(), channelId);
+ g_game().playerCloseChannel(player->getID(), channelId);
}
void ProtocolGame::parseOpenPrivateChannel(NetworkMessage &msg) {
- const std::string receiver = msg.getString();
- addGameTask(&Game::playerOpenPrivateChannel, player->getID(), receiver);
+ std::string receiver = msg.getString();
+ g_game().playerOpenPrivateChannel(player->getID(), receiver);
}
void ProtocolGame::parseAutoWalk(NetworkMessage &msg) {
@@ -1631,7 +1629,7 @@ void ProtocolGame::parseAutoWalk(NetworkMessage &msg) {
return;
}
- addGameTask(&Game::playerAutoWalk, player->getID(), path.data());
+ g_game().playerAutoWalk(player->getID(), path.data());
}
void ProtocolGame::parseSetOutfit(NetworkMessage &msg) {
@@ -1688,23 +1686,23 @@ void ProtocolGame::parseSetOutfit(NetworkMessage &msg) {
void ProtocolGame::parseToggleMount(NetworkMessage &msg) {
bool mount = msg.getByte() != 0;
- addGameTask(&Game::playerToggleMount, player->getID(), mount);
+ g_game().playerToggleMount(player->getID(), mount);
}
void ProtocolGame::parseApplyImbuement(NetworkMessage &msg) {
uint8_t slot = msg.getByte();
uint32_t imbuementId = msg.get();
bool protectionCharm = msg.getByte() != 0x00;
- addGameTask(&Game::playerApplyImbuement, player->getID(), imbuementId, slot, protectionCharm);
+ g_game().playerApplyImbuement(player->getID(), imbuementId, slot, protectionCharm);
}
void ProtocolGame::parseClearImbuement(NetworkMessage &msg) {
uint8_t slot = msg.getByte();
- addGameTask(&Game::playerClearImbuement, player->getID(), slot);
+ g_game().playerClearImbuement(player->getID(), slot);
}
void ProtocolGame::parseCloseImbuementWindow(NetworkMessage &) {
- addGameTask(&Game::playerCloseImbuementWindow, player->getID());
+ g_game().playerCloseImbuementWindow(player->getID());
}
void ProtocolGame::parseUseItem(NetworkMessage &msg) {
@@ -1712,7 +1710,7 @@ void ProtocolGame::parseUseItem(NetworkMessage &msg) {
uint16_t itemId = msg.get();
uint8_t stackpos = msg.getByte();
uint8_t index = msg.getByte();
- addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, "Game::playerUseItem", &Game::playerUseItem, player->getID(), pos, stackpos, index, itemId);
+ g_game().playerUseItem(player->getID(), pos, stackpos, index, itemId);
}
void ProtocolGame::parseUseItemEx(NetworkMessage &msg) {
@@ -1722,7 +1720,7 @@ void ProtocolGame::parseUseItemEx(NetworkMessage &msg) {
Position toPos = msg.getPosition();
uint16_t toItemId = msg.get();
uint8_t toStackPos = msg.getByte();
- addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, "Game::playerUseItemEx", &Game::playerUseItemEx, player->getID(), fromPos, fromStackPos, fromItemId, toPos, toStackPos, toItemId);
+ g_game().playerUseItemEx(player->getID(), fromPos, fromStackPos, fromItemId, toPos, toStackPos, toItemId);
}
void ProtocolGame::parseUseWithCreature(NetworkMessage &msg) {
@@ -1730,27 +1728,27 @@ void ProtocolGame::parseUseWithCreature(NetworkMessage &msg) {
uint16_t itemId = msg.get();
uint8_t fromStackPos = msg.getByte();
uint32_t creatureId = msg.get();
- addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, "Game::playerUseWithCreature", &Game::playerUseWithCreature, player->getID(), fromPos, fromStackPos, creatureId, itemId);
+ g_game().playerUseWithCreature(player->getID(), fromPos, fromStackPos, creatureId, itemId);
}
void ProtocolGame::parseCloseContainer(NetworkMessage &msg) {
uint8_t cid = msg.getByte();
- addGameTask(&Game::playerCloseContainer, player->getID(), cid);
+ g_game().playerCloseContainer(player->getID(), cid);
}
void ProtocolGame::parseUpArrowContainer(NetworkMessage &msg) {
uint8_t cid = msg.getByte();
- addGameTask(&Game::playerMoveUpContainer, player->getID(), cid);
+ g_game().playerMoveUpContainer(player->getID(), cid);
}
void ProtocolGame::parseUpdateContainer(NetworkMessage &msg) {
uint8_t cid = msg.getByte();
- addGameTask(&Game::playerUpdateContainer, player->getID(), cid);
+ g_game().playerUpdateContainer(player->getID(), cid);
}
void ProtocolGame::parseTeleport(NetworkMessage &msg) {
Position newPosition = msg.getPosition();
- addGameTask(&Game::playerTeleport, player->getID(), newPosition);
+ g_game().playerTeleport(player->getID(), newPosition);
}
void ProtocolGame::parseThrow(NetworkMessage &msg) {
@@ -1761,7 +1759,7 @@ void ProtocolGame::parseThrow(NetworkMessage &msg) {
uint8_t count = msg.getByte();
if (toPos != fromPos) {
- addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, "Game::playerMoveThing", &Game::playerMoveThing, player->getID(), fromPos, itemId, fromStackpos, toPos, count);
+ g_game().playerMoveThing(player->getID(), fromPos, itemId, fromStackpos, toPos, count);
}
}
@@ -1769,12 +1767,12 @@ void ProtocolGame::parseLookAt(NetworkMessage &msg) {
Position pos = msg.getPosition();
uint16_t itemId = msg.get();
uint8_t stackpos = msg.getByte();
- addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, "Game::playerLookAt", &Game::playerLookAt, player->getID(), itemId, pos, stackpos);
+ g_game().playerLookAt(player->getID(), itemId, pos, stackpos);
}
void ProtocolGame::parseLookInBattleList(NetworkMessage &msg) {
uint32_t creatureId = msg.get();
- addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, "Game::playerLookInBattleList", &Game::playerLookInBattleList, player->getID(), creatureId);
+ g_game().playerLookInBattleList(player->getID(), creatureId);
}
void ProtocolGame::parseQuickLoot(NetworkMessage &msg) {
@@ -1787,7 +1785,7 @@ void ProtocolGame::parseQuickLoot(NetworkMessage &msg) {
uint8_t stackpos = msg.getByte();
bool lootAllCorpses = msg.getByte();
bool autoLoot = msg.getByte();
- addGameTask(&Game::playerQuickLoot, player->getID(), pos, itemId, stackpos, nullptr, lootAllCorpses, autoLoot);
+ g_game().playerQuickLoot(player->getID(), pos, itemId, stackpos, nullptr, lootAllCorpses, autoLoot);
}
void ProtocolGame::parseLootContainer(NetworkMessage &msg) {
@@ -1801,29 +1799,29 @@ void ProtocolGame::parseLootContainer(NetworkMessage &msg) {
Position pos = msg.getPosition();
uint16_t itemId = msg.get();
uint8_t stackpos = msg.getByte();
- addGameTask(&Game::playerSetManagedContainer, player->getID(), category, pos, itemId, stackpos, true);
+ g_game().playerSetManagedContainer(player->getID(), category, pos, itemId, stackpos, true);
} else if (action == 1) {
ObjectCategory_t category = (ObjectCategory_t)msg.getByte();
- addGameTask(&Game::playerClearManagedContainer, player->getID(), category, true);
+ g_game().playerClearManagedContainer(player->getID(), category, true);
} else if (action == 2) {
ObjectCategory_t category = (ObjectCategory_t)msg.getByte();
- addGameTask(&Game::playerOpenManagedContainer, player->getID(), category, true);
+ g_game().playerOpenManagedContainer(player->getID(), category, true);
} else if (action == 3) {
bool useMainAsFallback = msg.getByte() == 1;
- addGameTask(&Game::playerSetQuickLootFallback, player->getID(), useMainAsFallback);
+ g_game().playerSetQuickLootFallback(player->getID(), useMainAsFallback);
} else if (action == 4) {
ObjectCategory_t category = (ObjectCategory_t)msg.getByte();
Position pos = msg.getPosition();
uint16_t itemId = msg.get();
uint8_t stackpos = msg.getByte();
g_logger().debug("[{}] action {}, category {}, pos {}, itemId {}, stackPos {}", __FUNCTION__, action, static_cast(category), pos.toString(), itemId, stackpos);
- addGameTask(&Game::playerSetManagedContainer, player->getID(), category, pos, itemId, stackpos, false);
+ g_game().playerSetManagedContainer(player->getID(), category, pos, itemId, stackpos, false);
} else if (action == 5) {
ObjectCategory_t category = (ObjectCategory_t)msg.getByte();
- addGameTask(&Game::playerClearManagedContainer, player->getID(), category, false);
+ g_game().playerClearManagedContainer(player->getID(), category, false);
} else if (action == 6) {
ObjectCategory_t category = (ObjectCategory_t)msg.getByte();
- addGameTask(&Game::playerOpenManagedContainer, player->getID(), category, false);
+ g_game().playerOpenManagedContainer(player->getID(), category, false);
}
g_logger().debug("[{}] action type {}", __FUNCTION__, action);
@@ -1844,7 +1842,7 @@ void ProtocolGame::parseQuickLootBlackWhitelist(NetworkMessage &msg) {
listedItems.push_back(msg.get());
}
- addGameTask(&Game::playerQuickLootBlackWhitelist, player->getID(), filter, listedItems);
+ g_game().playerQuickLootBlackWhitelist(player->getID(), filter, listedItems);
}
void ProtocolGame::parseSay(NetworkMessage &msg) {
@@ -1874,7 +1872,7 @@ void ProtocolGame::parseSay(NetworkMessage &msg) {
return;
}
- addGameTask(&Game::playerSay, player->getID(), channelId, type, receiver, text);
+ g_game().playerSay(player->getID(), channelId, type, receiver, text);
}
void ProtocolGame::parseFightModes(NetworkMessage &msg) {
@@ -1892,38 +1890,38 @@ void ProtocolGame::parseFightModes(NetworkMessage &msg) {
fightMode = FIGHTMODE_DEFENSE;
}
- addGameTask(&Game::playerSetFightModes, player->getID(), fightMode, rawChaseMode != 0, rawSecureMode != 0);
+ g_game().playerSetFightModes(player->getID(), fightMode, rawChaseMode != 0, rawSecureMode != 0);
}
void ProtocolGame::parseAttack(NetworkMessage &msg) {
uint32_t creatureId = msg.get();
// msg.get(); creatureId (same as above)
- addGameTask(&Game::playerSetAttackedCreature, player->getID(), creatureId);
+ g_game().playerSetAttackedCreature(player->getID(), creatureId);
}
void ProtocolGame::parseFollow(NetworkMessage &msg) {
uint32_t creatureId = msg.get();
// msg.get(); creatureId (same as above)
- addGameTask(&Game::playerFollowCreature, player->getID(), creatureId);
+ g_game().playerFollowCreature(player->getID(), creatureId);
}
void ProtocolGame::parseTextWindow(NetworkMessage &msg) {
uint32_t windowTextId = msg.get();
const std::string newText = msg.getString();
- addGameTask(&Game::playerWriteItem, player->getID(), windowTextId, newText);
+ g_game().playerWriteItem(player->getID(), windowTextId, newText);
}
void ProtocolGame::parseHouseWindow(NetworkMessage &msg) {
uint8_t doorId = msg.getByte();
uint32_t id = msg.get();
const std::string text = msg.getString();
- addGameTask(&Game::playerUpdateHouseWindow, player->getID(), doorId, id, text);
+ g_game().playerUpdateHouseWindow(player->getID(), doorId, id, text);
}
void ProtocolGame::parseLookInShop(NetworkMessage &msg) {
uint16_t id = msg.get();
uint8_t count = msg.getByte();
- addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, "Game::playerLookInShop", &Game::playerLookInShop, player->getID(), id, count);
+ g_game().playerLookInShop(player->getID(), id, count);
}
void ProtocolGame::parsePlayerBuyOnShop(NetworkMessage &msg) {
@@ -1932,7 +1930,7 @@ void ProtocolGame::parsePlayerBuyOnShop(NetworkMessage &msg) {
uint16_t amount = oldProtocol ? static_cast(msg.getByte()) : msg.get();
bool ignoreCap = msg.getByte() != 0;
bool inBackpacks = msg.getByte() != 0;
- addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, "Game::playerBuyItem", &Game::playerBuyItem, player->getID(), id, count, amount, ignoreCap, inBackpacks);
+ g_game().playerBuyItem(player->getID(), id, count, amount, ignoreCap, inBackpacks);
}
void ProtocolGame::parsePlayerSellOnShop(NetworkMessage &msg) {
@@ -1941,7 +1939,7 @@ void ProtocolGame::parsePlayerSellOnShop(NetworkMessage &msg) {
uint16_t amount = oldProtocol ? static_cast(msg.getByte()) : msg.get();
bool ignoreEquipped = msg.getByte() != 0;
- addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, "Game::playerSellItem", &Game::playerSellItem, player->getID(), id, count, amount, ignoreEquipped);
+ g_game().playerSellItem(player->getID(), id, count, amount, ignoreEquipped);
}
void ProtocolGame::parseRequestTrade(NetworkMessage &msg) {
@@ -1949,23 +1947,23 @@ void ProtocolGame::parseRequestTrade(NetworkMessage &msg) {
uint16_t itemId = msg.get();
uint8_t stackpos = msg.getByte();
uint32_t playerId = msg.get();
- addGameTask(&Game::playerRequestTrade, player->getID(), pos, stackpos, playerId, itemId);
+ g_game().playerRequestTrade(player->getID(), pos, stackpos, playerId, itemId);
}
void ProtocolGame::parseLookInTrade(NetworkMessage &msg) {
bool counterOffer = (msg.getByte() == 0x01);
uint8_t index = msg.getByte();
- addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, "Game::playerLookInTrade", &Game::playerLookInTrade, player->getID(), counterOffer, index);
+ g_game().playerLookInTrade(player->getID(), counterOffer, index);
}
void ProtocolGame::parseAddVip(NetworkMessage &msg) {
const std::string name = msg.getString();
- addGameTask(&Game::playerRequestAddVip, player->getID(), name);
+ g_game().playerRequestAddVip(player->getID(), name);
}
void ProtocolGame::parseRemoveVip(NetworkMessage &msg) {
uint32_t guid = msg.get();
- addGameTask(&Game::playerRequestRemoveVip, player->getID(), guid);
+ g_game().playerRequestRemoveVip(player->getID(), guid);
}
void ProtocolGame::parseEditVip(NetworkMessage &msg) {
@@ -1973,7 +1971,7 @@ void ProtocolGame::parseEditVip(NetworkMessage &msg) {
const std::string description = msg.getString();
uint32_t icon = std::min(10, msg.get()); // 10 is max icon in 9.63
bool notify = msg.getByte() != 0;
- addGameTask(&Game::playerRequestEditVip, player->getID(), guid, description, icon, notify);
+ g_game().playerRequestEditVip(player->getID(), guid, description, icon, notify);
}
void ProtocolGame::parseRotateItem(NetworkMessage &msg) {
@@ -1982,9 +1980,9 @@ void ProtocolGame::parseRotateItem(NetworkMessage &msg) {
uint8_t stackpos = msg.getByte();
const auto &itemType = Item::items[itemId];
if (itemType.isPodium) {
- addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, "Game::playerRotatePodium", &Game::playerRotatePodium, player->getID(), pos, stackpos, itemId);
+ g_game().playerRotatePodium(player->getID(), pos, stackpos, itemId);
} else {
- addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, "Game::playerRotateItem", &Game::playerRotateItem, player->getID(), pos, stackpos, itemId);
+ g_game().playerRotateItem(player->getID(), pos, stackpos, itemId);
}
}
@@ -1992,7 +1990,7 @@ void ProtocolGame::parseWrapableItem(NetworkMessage &msg) {
Position pos = msg.getPosition();
uint16_t itemId = msg.get();
uint8_t stackpos = msg.getByte();
- addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, "Game::playerWrapableItem", &Game::playerWrapableItem, player->getID(), pos, stackpos, itemId);
+ g_game().playerWrapableItem(player->getID(), pos, stackpos, itemId);
}
void ProtocolGame::parseInspectionObject(NetworkMessage &msg) {
@@ -2106,7 +2104,7 @@ void ProtocolGame::parseTaskHuntingAction(NetworkMessage &msg) {
return;
}
- addGameTask(&Game::playerTaskHuntingAction, player->getID(), slot, action, upgrade, raceId);
+ g_game().playerTaskHuntingAction(player->getID(), slot, action, upgrade, raceId);
}
void ProtocolGame::sendHighscoresNoData() {
@@ -2220,7 +2218,7 @@ void ProtocolGame::parseRuleViolationReport(NetworkMessage &msg) {
msg.get(); // statement id, used to get whatever player have said, we don't log that.
}
- addGameTask(&Game::playerReportRuleViolationReport, player->getID(), targetName, reportType, reportReason, comment, translation);
+ g_game().playerReportRuleViolationReport(player->getID(), targetName, reportType, reportReason, comment, translation);
}
void ProtocolGame::parseBestiarysendRaces() {
@@ -2942,12 +2940,12 @@ void ProtocolGame::parseBugReport(NetworkMessage &msg) {
position = msg.getPosition();
}
- addGameTask(&Game::playerReportBug, player->getID(), message, position, category);
+ g_game().playerReportBug(player->getID(), message, position, category);
}
void ProtocolGame::parseGreet(NetworkMessage &msg) {
uint32_t npcId = msg.get();
- addGameTask(&Game::playerNpcGreet, player->getID(), npcId);
+ g_game().playerNpcGreet(player->getID(), npcId);
}
void ProtocolGame::parseDebugAssert(NetworkMessage &msg) {
@@ -2961,7 +2959,7 @@ void ProtocolGame::parseDebugAssert(NetworkMessage &msg) {
std::string date = msg.getString();
std::string description = msg.getString();
std::string comment = msg.getString();
- addGameTask(&Game::playerDebugAssert, player->getID(), assertLine, date, description, comment);
+ g_game().playerDebugAssert(player->getID(), assertLine, date, description, comment);
}
void ProtocolGame::parsePreyAction(NetworkMessage &msg) {
@@ -2982,7 +2980,7 @@ void ProtocolGame::parsePreyAction(NetworkMessage &msg) {
return;
}
- addGameTask(&Game::playerPreyAction, player->getID(), slot, action, option, index, raceId);
+ g_game().playerPreyAction(player->getID(), slot, action, option, index, raceId);
}
void ProtocolGame::parseSendResourceBalance() {
@@ -3001,52 +2999,52 @@ void ProtocolGame::parseSendResourceBalance() {
void ProtocolGame::parseInviteToParty(NetworkMessage &msg) {
uint32_t targetId = msg.get();
- addGameTask(&Game::playerInviteToParty, player->getID(), targetId);
+ g_game().playerInviteToParty(player->getID(), targetId);
}
void ProtocolGame::parseJoinParty(NetworkMessage &msg) {
uint32_t targetId = msg.get();
- addGameTask(&Game::playerJoinParty, player->getID(), targetId);
+ g_game().playerJoinParty(player->getID(), targetId);
}
void ProtocolGame::parseRevokePartyInvite(NetworkMessage &msg) {
uint32_t targetId = msg.get();
- addGameTask(&Game::playerRevokePartyInvitation, player->getID(), targetId);
+ g_game().playerRevokePartyInvitation(player->getID(), targetId);
}
void ProtocolGame::parsePassPartyLeadership(NetworkMessage &msg) {
uint32_t targetId = msg.get();
- addGameTask(&Game::playerPassPartyLeadership, player->getID(), targetId);
+ g_game().playerPassPartyLeadership(player->getID(), targetId);
}
void ProtocolGame::parseEnableSharedPartyExperience(NetworkMessage &msg) {
bool sharedExpActive = msg.getByte() == 1;
- addGameTask(&Game::playerEnableSharedPartyExperience, player->getID(), sharedExpActive);
+ g_game().playerEnableSharedPartyExperience(player->getID(), sharedExpActive);
}
void ProtocolGame::parseQuestLine(NetworkMessage &msg) {
uint16_t questId = msg.get();
- addGameTask(&Game::playerShowQuestLine, player->getID(), questId);
+ g_game().playerShowQuestLine(player->getID(), questId);
}
void ProtocolGame::parseMarketLeave() {
- addGameTask(&Game::playerLeaveMarket, player->getID());
+ g_game().playerLeaveMarket(player->getID());
}
void ProtocolGame::parseMarketBrowse(NetworkMessage &msg) {
uint16_t browseId = oldProtocol ? msg.get() : static_cast(msg.getByte());
if ((oldProtocol && browseId == MARKETREQUEST_OWN_OFFERS_OLD) || (!oldProtocol && browseId == MARKETREQUEST_OWN_OFFERS)) {
- addGameTask(&Game::playerBrowseMarketOwnOffers, player->getID());
+ g_game().playerBrowseMarketOwnOffers(player->getID());
} else if ((oldProtocol && browseId == MARKETREQUEST_OWN_HISTORY_OLD) || (!oldProtocol && browseId == MARKETREQUEST_OWN_HISTORY)) {
- addGameTask(&Game::playerBrowseMarketOwnHistory, player->getID());
+ g_game().playerBrowseMarketOwnHistory(player->getID());
} else if (!oldProtocol) {
uint16_t itemId = msg.get();
uint8_t tier = msg.get();
player->sendMarketEnter(player->getLastDepotId());
- addGameTask(&Game::playerBrowseMarket, player->getID(), itemId, tier);
+ g_game().playerBrowseMarket(player->getID(), itemId, tier);
} else {
- addGameTask(&Game::playerBrowseMarket, player->getID(), browseId, 0);
+ g_game().playerBrowseMarket(player->getID(), browseId, 0);
}
}
@@ -3062,7 +3060,7 @@ void ProtocolGame::parseMarketCreateOffer(NetworkMessage &msg) {
uint64_t price = oldProtocol ? static_cast(msg.get()) : msg.get