diff --git a/README.md b/README.md index 16b6d73cb14..d3d83eecc48 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ source of the Canary, so that it will be the first repository to use this engine To connect to the server and to take a stable experience, you can use [mehah's otclient](https://github.com/mehah/otclient) or [tibia client](https://github.com/dudantas/tibia-client/releases/latest) and if you want to edit something, check -our [customized tools](https://docs.opentibiabr.com/others/downloads/tools). +our [customized tools](https://docs.opentibiabr.com/opentibiabr/downloads/tools). If you want edit the map, use the [own remere's map editor](https://github.com/opentibiabr/remeres-map-editor/). diff --git a/config.lua.dist b/config.lua.dist index 76508f6d7d7..a00bb061f81 100644 --- a/config.lua.dist +++ b/config.lua.dist @@ -186,6 +186,7 @@ onlyPremiumAccount = false -- NOTE: buyAolCommandFee will add fee when player buy aol by command (!aol), active changing value more than 0 (fee value. ex: 1 = 1gp aol will be 50001) -- NOTE: buyBlessCommandFee will add fee when player buy bless by command (!bless), active changing value between 1 and 100 (fee percent. ex: 3 = 3%, 30 = 30%) -- NOTE: teleportPlayerToVocationRoom will enable oressa to teleport player to his/her room vocation +-- NOTE: toggleReceiveReward = true, will enable players to choose one of reward exercise weapon by command !reward weatherRain = false thunderEffect = false allConsoleLog = false @@ -200,6 +201,7 @@ toggleTravelsFree = false buyAolCommandFee = 0 buyBlessCommandFee = 0 teleportPlayerToVocationRoom = true +toggleReceiveReward = false -- 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 d5f434274b0..b1795ce1dde 100644 --- a/data-otservbr-global/lib/core/storages.lua +++ b/data-otservbr-global/lib/core/storages.lua @@ -140,7 +140,7 @@ Storage = { PremiumAccount = 30058, BattleAxeQuest = 30059, ShrineEntrance = 30060, - + PlayerWeaponReward = 30061, --[[ Old storages Over time, this will be dropped and replaced by the table above diff --git a/data-otservbr-global/monster/bosses/doctor_marrow.lua b/data-otservbr-global/monster/bosses/doctor_marrow.lua new file mode 100644 index 00000000000..3de9bc41825 --- /dev/null +++ b/data-otservbr-global/monster/bosses/doctor_marrow.lua @@ -0,0 +1,110 @@ +local mType = Game.createMonsterType("Doctor Marrow") +local monster = {} + +monster.description = "Doctor Marrow" +monster.experience = 0 +monster.outfit = { + lookType = 1611, + lookHead = 57, + lookBody = 0, + lookLegs = 0, + lookFeet = 95, + lookAddons = 0, + lookMount = 0, +} + +monster.health = 1800 +monster.maxHealth = 1800 +monster.race = "blood" +monster.corpse = 18074 +monster.speed = 125 +monster.manaCost = 0 + +monster.changeTarget = { + interval = 4000, + chance = 10, +} + +monster.strategiesTarget = { + nearest = 80, + health = 10, + damage = 10, +} + +monster.flags = { + summonable = false, + attackable = true, + hostile = true, + convinceable = false, + pushable = false, + rewardBoss = true, + illusionable = false, + canPushItems = true, + canPushCreatures = true, + critChance = 10, + staticAttackChance = 90, + targetDistance = 1, + runHealth = 0, + healthHidden = false, + isBlockable = false, + canWalkOnEnergy = true, + canWalkOnFire = true, + canWalkOnPoison = true, +} + +monster.light = { + level = 0, + color = 0, +} + +monster.voices = { + interval = 5000, + chance = 10, + { text = "You can't stop the future!", yell = false }, +} + +monster.attacks = { + { name = "melee", interval = 2000, chance = 100, minDamage = 0, maxDamage = -2800 }, +} + +monster.defenses = { + defense = 54, + armor = 59, + mitigation = 3.7, +} + +monster.elements = { + { type = COMBAT_PHYSICALDAMAGE, percent = 0 }, + { type = COMBAT_ENERGYDAMAGE, percent = 0 }, + { type = COMBAT_EARTHDAMAGE, percent = 0 }, + { type = COMBAT_FIREDAMAGE, percent = 0 }, + { type = COMBAT_LIFEDRAIN, percent = 0 }, + { type = COMBAT_MANADRAIN, percent = 0 }, + { type = COMBAT_DROWNDAMAGE, percent = 0 }, + { type = COMBAT_ICEDAMAGE, percent = 0 }, + { type = COMBAT_HOLYDAMAGE, percent = 0 }, + { type = COMBAT_DEATHDAMAGE, percent = 0 }, +} + +monster.immunities = { + { type = "paralyze", condition = true }, + { type = "outfit", condition = false }, + { type = "invisible", condition = true }, + { type = "bleed", condition = false }, +} + +mType.onThink = function(monster, interval) end + +mType.onAppear = function(monster, creature) + if monster:getType():isRewardBoss() then + monster:setReward(true) + end +end + +mType.onDisappear = function(monster, creature) end + +mType.onMove = function(monster, creature, fromPosition, toPosition) end + +mType.onSay = function(monster, creature, type, message) end + +mType:register(monster) diff --git a/data-otservbr-global/scripts/creaturescripts/customs/reward_exercise.lua b/data-otservbr-global/scripts/creaturescripts/customs/reward_exercise.lua new file mode 100644 index 00000000000..f17304cec00 --- /dev/null +++ b/data-otservbr-global/scripts/creaturescripts/customs/reward_exercise.lua @@ -0,0 +1,13 @@ +local winReward = CreatureEvent("WinReward") + +function winReward.onLogin(player) + if configManager.getBoolean(configKeys.TOGGLE_RECEIVE_REWARD) and player:getTown():getId() >= TOWNS_LIST.AB_DENDRIEL then + -- check user won exercise weapon and send message + if player:getStorageValue(tonumber(Storage.PlayerWeaponReward)) ~= 1 then + player:sendTextMessage(MESSAGE_LOGIN, "You can receive an exercise weapon using command !reward") + end + end + return true +end + +winReward:register() diff --git a/data-otservbr-global/scripts/globalevents/worldchanges/their_masters_voice.lua b/data-otservbr-global/scripts/globalevents/worldchanges/their_masters_voice.lua index fa1b9adbe33..2061c254cf9 100644 --- a/data-otservbr-global/scripts/globalevents/worldchanges/their_masters_voice.lua +++ b/data-otservbr-global/scripts/globalevents/worldchanges/their_masters_voice.lua @@ -12,7 +12,7 @@ function theirmastersvoice.onStartup() if item then local slimeChance = math.random(100) if slimeChance <= 30 then - item:transform(math.random(13585, 13589)) + item:transform(math.random(12059, 12063)) position:sendMagicEffect(CONST_ME_YELLOW_RINGS) end end diff --git a/data-otservbr-global/scripts/lib/register_monster_type.lua b/data-otservbr-global/scripts/lib/register_monster_type.lua index 68983418159..21a10d94aac 100644 --- a/data-otservbr-global/scripts/lib/register_monster_type.lua +++ b/data-otservbr-global/scripts/lib/register_monster_type.lua @@ -199,6 +199,9 @@ registerMonsterType.flags = function(mtype, mask) if mask.flags.canPushCreatures ~= nil then mtype:canPushCreatures(mask.flags.canPushCreatures) end + if mask.flags.critChance ~= nil then + mtype:critChance(mask.flags.critChance) + end if mask.flags.targetDistance then mtype:targetDistance(math.max(1, mask.flags.targetDistance)) end diff --git a/data-otservbr-global/world/world_changes/fury_gates/abdendriel.otbm b/data-otservbr-global/world/world_changes/fury_gates/abdendriel.otbm index 9e6b2698eee..c41c56415e9 100644 Binary files a/data-otservbr-global/world/world_changes/fury_gates/abdendriel.otbm and b/data-otservbr-global/world/world_changes/fury_gates/abdendriel.otbm differ diff --git a/data-otservbr-global/world/world_changes/fury_gates/ankrahmun.otbm b/data-otservbr-global/world/world_changes/fury_gates/ankrahmun.otbm index 04b378fa578..d426bf44223 100644 Binary files a/data-otservbr-global/world/world_changes/fury_gates/ankrahmun.otbm and b/data-otservbr-global/world/world_changes/fury_gates/ankrahmun.otbm differ diff --git a/data-otservbr-global/world/world_changes/fury_gates/carlin.otbm b/data-otservbr-global/world/world_changes/fury_gates/carlin.otbm index a112b2e45e6..15f3fc688b6 100644 Binary files a/data-otservbr-global/world/world_changes/fury_gates/carlin.otbm and b/data-otservbr-global/world/world_changes/fury_gates/carlin.otbm differ diff --git a/data-otservbr-global/world/world_changes/fury_gates/darashia.otbm b/data-otservbr-global/world/world_changes/fury_gates/darashia.otbm index 5f96244586b..4e259396824 100644 Binary files a/data-otservbr-global/world/world_changes/fury_gates/darashia.otbm and b/data-otservbr-global/world/world_changes/fury_gates/darashia.otbm differ diff --git a/data-otservbr-global/world/world_changes/fury_gates/edron.otbm b/data-otservbr-global/world/world_changes/fury_gates/edron.otbm index 72d3239b4bb..3ad2c77ca4a 100644 Binary files a/data-otservbr-global/world/world_changes/fury_gates/edron.otbm and b/data-otservbr-global/world/world_changes/fury_gates/edron.otbm differ diff --git a/data-otservbr-global/world/world_changes/fury_gates/kazordoon.otbm b/data-otservbr-global/world/world_changes/fury_gates/kazordoon.otbm index c1aa4744aac..4a6e4386f29 100644 Binary files a/data-otservbr-global/world/world_changes/fury_gates/kazordoon.otbm and b/data-otservbr-global/world/world_changes/fury_gates/kazordoon.otbm differ diff --git a/data-otservbr-global/world/world_changes/fury_gates/libertybay.otbm b/data-otservbr-global/world/world_changes/fury_gates/libertybay.otbm index ac1df9d0950..c9a57e0f45f 100644 Binary files a/data-otservbr-global/world/world_changes/fury_gates/libertybay.otbm and b/data-otservbr-global/world/world_changes/fury_gates/libertybay.otbm differ diff --git a/data-otservbr-global/world/world_changes/fury_gates/porthope.otbm b/data-otservbr-global/world/world_changes/fury_gates/porthope.otbm index f0b1b943c76..2232ecbc988 100644 Binary files a/data-otservbr-global/world/world_changes/fury_gates/porthope.otbm and b/data-otservbr-global/world/world_changes/fury_gates/porthope.otbm differ diff --git a/data-otservbr-global/world/world_changes/fury_gates/thais.otbm b/data-otservbr-global/world/world_changes/fury_gates/thais.otbm index dfb1039d07b..a131dd8d096 100644 Binary files a/data-otservbr-global/world/world_changes/fury_gates/thais.otbm and b/data-otservbr-global/world/world_changes/fury_gates/thais.otbm differ diff --git a/data-otservbr-global/world/world_changes/fury_gates/venore.otbm b/data-otservbr-global/world/world_changes/fury_gates/venore.otbm index 1ca21d586d1..1922f21ab60 100644 Binary files a/data-otservbr-global/world/world_changes/fury_gates/venore.otbm and b/data-otservbr-global/world/world_changes/fury_gates/venore.otbm differ diff --git a/data/events/scripts/player.lua b/data/events/scripts/player.lua index f176e5000c5..816aa523b70 100644 --- a/data/events/scripts/player.lua +++ b/data/events/scripts/player.lua @@ -445,6 +445,7 @@ end function Player:onReportBug(message, position, category) local name = self:getName() + FS.mkdir_p(string.format("%s/reports/bugs/%s", CORE_DIRECTORY, name)) local file = io.open(string.format("%s/reports/bugs/%s/report.txt", CORE_DIRECTORY, name), "a") if not file then diff --git a/data/items/items.xml b/data/items/items.xml index 8c826d3fd64..d23468cabf3 100644 --- a/data/items/items.xml +++ b/data/items/items.xml @@ -15098,7 +15098,6 @@ - diff --git a/data/libs/functions/fs.lua b/data/libs/functions/fs.lua new file mode 100644 index 00000000000..f95fba51b05 --- /dev/null +++ b/data/libs/functions/fs.lua @@ -0,0 +1,32 @@ +FS = {} + +function FS.exists(path) + local file = io.open(path, "r") + if file then + file:close() + return true + end + return false +end + +function FS.mkdir(path) + if FS.exists(path) then + return true + end + local success, err = os.execute("mkdir " .. path) + if not success then + return false, err + end + return true +end + +function FS.mkdir_p(path) + if path == "" then + return true + end + if FS.exists(path) then + return true + end + FS.mkdir_p(path:match("(.*[/\\])")) + return FS.mkdir(path) +end diff --git a/data/libs/functions/load.lua b/data/libs/functions/load.lua index 705fdf712d6..0ab33f5de11 100644 --- a/data/libs/functions/load.lua +++ b/data/libs/functions/load.lua @@ -5,6 +5,7 @@ dofile(CORE_DIRECTORY .. "/libs/functions/constants.lua") dofile(CORE_DIRECTORY .. "/libs/functions/container.lua") dofile(CORE_DIRECTORY .. "/libs/functions/creature.lua") dofile(CORE_DIRECTORY .. "/libs/functions/functions.lua") +dofile(CORE_DIRECTORY .. "/libs/functions/fs.lua") dofile(CORE_DIRECTORY .. "/libs/functions/game.lua") dofile(CORE_DIRECTORY .. "/libs/functions/item.lua") dofile(CORE_DIRECTORY .. "/libs/functions/itemtype.lua") diff --git a/data/scripts/talkactions/player/reward.lua b/data/scripts/talkactions/player/reward.lua new file mode 100644 index 00000000000..7c2999a587e --- /dev/null +++ b/data/scripts/talkactions/player/reward.lua @@ -0,0 +1,65 @@ +local config = { + items = { + { id = 35284, charges = 64000 }, + { id = 35279, charges = 64000 }, + { id = 35281, charges = 64000 }, + { id = 35283, charges = 64000 }, + { id = 35282, charges = 64000 }, + { id = 35280, charges = 64000 }, + }, + storage = tonumber(Storage.PlayerWeaponReward), -- storage key, player can only win once +} + +local function sendExerciseRewardModal(player) + local window = ModalWindow({ + title = "Exercise Reward", + message = "choose a item", + }) + for _, it in pairs(config.items) do + local iType = ItemType(it.id) + if iType then + window:addChoice(iType:getName(), function(player, button, choice) + if button.name ~= "Select" then + return true + end + + local inbox = player:getSlotItem(CONST_SLOT_STORE_INBOX) + if inbox and inbox:getEmptySlots() > 0 then + local item = inbox:addItem(it.id, it.charges) + if item then + item:setAttribute(ITEM_ATTRIBUTE_STORE, systemTime()) + else + player:sendTextMessage(MESSAGE_LOOK, "You need to have capacity and empty slots to receive.") + return + end + player:sendTextMessage(MESSAGE_LOOK, string.format("Congratulations, you received a %s with %i charges in your store inbox.", iType:getName(), it.charges)) + player:setStorageValue(config.storage, 1) + else + player:sendTextMessage(MESSAGE_LOOK, "You need to have capacity and empty slots to receive.") + end + end) + end + end + window:addButton("Select") + window:addButton("Close") + window:setDefaultEnterButton(0) + window:setDefaultEscapeButton(1) + window:sendToPlayer(player) +end + +local exerciseRewardModal = TalkAction("!reward") +function exerciseRewardModal.onSay(player, words, param) + if not configManager.getBoolean(configKeys.TOGGLE_RECEIVE_REWARD) or player:getTown():getId() < TOWNS_LIST.AB_DENDRIEL then + return true + end + if player:getStorageValue(config.storage) > 0 then + player:sendTextMessage(MESSAGE_LOOK, "You already received your exercise weapon reward!") + return true + end + sendExerciseRewardModal(player) + return true +end + +exerciseRewardModal:separator(" ") +exerciseRewardModal:groupType("normal") +exerciseRewardModal:register() diff --git a/src/config/config_definitions.hpp b/src/config/config_definitions.hpp index 6a785280e56..d3bf0b87eec 100644 --- a/src/config/config_definitions.hpp +++ b/src/config/config_definitions.hpp @@ -91,6 +91,8 @@ enum booleanConfig_t { TOGGLE_MOUNT_IN_PZ, TOGGLE_HOUSE_TRANSFER_ON_SERVER_RESTART, + TOGGLE_RECEIVE_REWARD, + LAST_BOOLEAN_CONFIG }; diff --git a/src/config/configmanager.cpp b/src/config/configmanager.cpp index 940ea29eb51..d0abcc9352b 100644 --- a/src/config/configmanager.cpp +++ b/src/config/configmanager.cpp @@ -12,7 +12,6 @@ #include "config/configmanager.hpp" #include "declarations.hpp" #include "game/game.hpp" -#include "lua/scripts/luajit_sync.hpp" #include "server/network/webhook/webhook.hpp" #if LUA_VERSION_NUM >= 502 @@ -393,6 +392,8 @@ bool ConfigManager::load() { boolean[TOGGLE_HOUSE_TRANSFER_ON_SERVER_RESTART] = getGlobalBoolean(L, "togglehouseTransferOnRestart", false); + boolean[TOGGLE_RECEIVE_REWARD] = getGlobalBoolean(L, "toggleReceiveReward", false); + loaded = true; lua_close(L); return true; diff --git a/src/creatures/combat/combat.cpp b/src/creatures/combat/combat.cpp index 4a8e6bd7060..75cec14c30f 100644 --- a/src/creatures/combat/combat.cpp +++ b/src/creatures/combat/combat.cpp @@ -73,7 +73,7 @@ CombatDamage Combat::getCombatDamage(std::shared_ptr creature, std::sh ); } else if (formulaType == COMBAT_FORMULA_SKILL) { std::shared_ptr tool = player->getWeapon(); - const Weapon* weapon = g_weapons().getWeapon(tool); + const WeaponShared_ptr weapon = g_weapons().getWeapon(tool); if (weapon) { damage.primary.value = normal_random( static_cast(minb), @@ -1139,41 +1139,7 @@ void Combat::doCombatHealth(std::shared_ptr caster, std::shared_ptrgetPlayer()) { - // Critical damage - uint16_t chance = caster->getPlayer()->getSkillLevel(SKILL_CRITICAL_HIT_CHANCE) + (uint16_t)damage.criticalChance; - // Charm low blow rune) - if (target && target->getMonster() && damage.primary.type != COMBAT_HEALING) { - uint16_t playerCharmRaceid = caster->getPlayer()->parseRacebyCharm(CHARM_LOW, false, 0); - if (playerCharmRaceid != 0) { - const auto mType = g_monsters().getMonsterType(target->getName()); - if (mType && playerCharmRaceid == mType->info.raceid) { - const auto charm = g_iobestiary().getBestiaryCharm(CHARM_LOW); - if (charm) { - chance += charm->percent; - g_game().sendDoubleSoundEffect(target->getPosition(), charm->soundCastEffect, charm->soundImpactEffect, caster); - } - } - } - } - if (chance != 0 && uniform_random(1, 100) <= chance) { - damage.critical = true; - damage.primary.value += (damage.primary.value * (caster->getPlayer()->getSkillLevel(SKILL_CRITICAL_HIT_DAMAGE) + damage.criticalDamage)) / 100; - damage.secondary.value += (damage.secondary.value * (caster->getPlayer()->getSkillLevel(SKILL_CRITICAL_HIT_DAMAGE) + damage.criticalDamage)) / 100; - } - - // Fatal hit (onslaught) - if (auto playerWeapon = caster->getPlayer()->getInventoryItem(CONST_SLOT_LEFT); - playerWeapon != nullptr && playerWeapon->getTier()) { - double_t fatalChance = playerWeapon->getFatalChance(); - double_t randomChance = uniform_random(0, 10000) / 100; - if (damage.primary.type != COMBAT_HEALING && fatalChance > 0 && randomChance < fatalChance) { - damage.fatal = true; - damage.primary.value += static_cast(std::round(damage.primary.value * 0.6)); - damage.secondary.value += static_cast(std::round(damage.secondary.value * 0.6)); - } - } - } + applyExtensions(caster, target, damage, params); if (canCombat) { if (target && caster && params.distanceEffect != CONST_ANI_NONE) { @@ -1194,27 +1160,7 @@ void Combat::doCombatHealth(std::shared_ptr caster, std::shared_ptr caster, const Position &position, const std::unique_ptr &area, CombatDamage &damage, const CombatParams ¶ms) { - if (caster && caster->getPlayer()) { - // Critical damage - uint16_t chance = caster->getPlayer()->getSkillLevel(SKILL_CRITICAL_HIT_CHANCE) + (uint16_t)damage.criticalChance; - if (damage.primary.type != COMBAT_HEALING && chance != 0 && uniform_random(1, 100) <= chance) { - damage.critical = true; - damage.primary.value += (damage.primary.value * (caster->getPlayer()->getSkillLevel(SKILL_CRITICAL_HIT_DAMAGE) + damage.criticalDamage)) / 100; - damage.secondary.value += (damage.secondary.value * (caster->getPlayer()->getSkillLevel(SKILL_CRITICAL_HIT_DAMAGE) + damage.criticalDamage)) / 100; - } - - // Fatal hit (onslaught) - if (auto playerWeapon = caster->getPlayer()->getInventoryItem(CONST_SLOT_LEFT); - playerWeapon != nullptr && playerWeapon->getTier() > 0) { - double_t fatalChance = playerWeapon->getFatalChance(); - double_t randomChance = uniform_random(0, 10000) / 100; - if (damage.primary.type != COMBAT_HEALING && fatalChance > 0 && randomChance < fatalChance) { - damage.fatal = true; - damage.primary.value += static_cast(std::round(damage.primary.value * 0.6)); - damage.secondary.value += static_cast(std::round(damage.secondary.value * 0.6)); - } - } - } + applyExtensions(caster, nullptr, damage, params); const auto origin = caster ? caster->getPosition() : Position(); CombatFunc(caster, origin, position, area, params, CombatHealthFunc, &damage); } @@ -1231,15 +1177,7 @@ void Combat::doCombatMana(std::shared_ptr caster, std::shared_ptrgetPosition(), params.impactEffect); } - if (caster && caster->getPlayer()) { - // Critical damage - uint16_t chance = caster->getPlayer()->getSkillLevel(SKILL_CRITICAL_HIT_CHANCE) + (uint16_t)damage.criticalChance; - if (chance != 0 && uniform_random(1, 100) <= chance) { - damage.critical = true; - damage.primary.value += (damage.primary.value * (caster->getPlayer()->getSkillLevel(SKILL_CRITICAL_HIT_DAMAGE) + damage.criticalDamage)) / 100; - damage.secondary.value += (damage.secondary.value * (caster->getPlayer()->getSkillLevel(SKILL_CRITICAL_HIT_DAMAGE) + damage.criticalDamage)) / 100; - } - } + applyExtensions(caster, target, damage, params); if (canCombat) { if (caster && target && params.distanceEffect != CONST_ANI_NONE) { @@ -1260,15 +1198,7 @@ void Combat::doCombatMana(std::shared_ptr caster, std::shared_ptr caster, const Position &position, const std::unique_ptr &area, CombatDamage &damage, const CombatParams ¶ms) { - if (caster && caster->getPlayer()) { - // Critical damage - uint16_t chance = caster->getPlayer()->getSkillLevel(SKILL_CRITICAL_HIT_CHANCE) + (uint16_t)damage.criticalChance; - if (chance != 0 && uniform_random(1, 100) <= chance) { - damage.critical = true; - damage.primary.value += (damage.primary.value * (caster->getPlayer()->getSkillLevel(SKILL_CRITICAL_HIT_DAMAGE) + damage.criticalDamage)) / 100; - damage.secondary.value += (damage.secondary.value * (caster->getPlayer()->getSkillLevel(SKILL_CRITICAL_HIT_DAMAGE) + damage.criticalDamage)) / 100; - } - } + applyExtensions(caster, nullptr, damage, params); const auto origin = caster ? caster->getPosition() : Position(); CombatFunc(caster, origin, position, area, params, CombatManaFunc, &damage); } @@ -1514,7 +1444,7 @@ void ValueCallback::getMinMaxValues(std::shared_ptr player, CombatDamage case COMBAT_FORMULA_SKILL: { // onGetPlayerMinMaxValues(player, attackSkill, attackValue, attackFactor) std::shared_ptr tool = player->getWeapon(); - const Weapon* weapon = g_weapons().getWeapon(tool); + const WeaponShared_ptr weapon = g_weapons().getWeapon(tool); std::shared_ptr item = nullptr; if (weapon) { @@ -1768,13 +1698,15 @@ bool ChainPickerCallback::onChainCombat(std::shared_ptr creature, std: //**********************************************************// void AreaCombat::clear() { - areas.clear(); + std::ranges::fill(areas, nullptr); } AreaCombat::AreaCombat(const AreaCombat &rhs) { hasExtArea = rhs.hasExtArea; - for (const auto &it : rhs.areas) { - areas[it.first] = it.second->clone(); + for (uint_fast8_t i = 0; i <= Direction::DIRECTION_LAST; ++i) { + if (const auto &area = rhs.areas[i]) { + areas[i] = area->clone(); + } } } @@ -2078,3 +2010,64 @@ void MagicField::onStepInField(const std::shared_ptr &creature) { creature->addCondition(conditionCopy); } } + +void Combat::applyExtensions(std::shared_ptr caster, std::shared_ptr target, CombatDamage &damage, const CombatParams ¶ms) { + if (damage.extension || !caster || damage.primary.type == COMBAT_HEALING) { + return; + } + + g_logger().debug("[Combat::applyExtensions] - Applying extensions for {} on {}. Initial damage: {}", caster->getName(), target ? target->getName() : "null", damage.primary.value); + + // Critical hit + uint16_t chance = 0; + int32_t multiplier = 50; + auto player = caster->getPlayer(); + auto monster = caster->getMonster(); + if (player) { + chance = player->getSkillLevel(SKILL_CRITICAL_HIT_CHANCE); + multiplier = player->getSkillLevel(SKILL_CRITICAL_HIT_DAMAGE); + + if (target) { + uint16_t playerCharmRaceid = player->parseRacebyCharm(CHARM_LOW, false, 0); + if (playerCharmRaceid != 0) { + const auto mType = g_monsters().getMonsterType(target->getName()); + if (mType && playerCharmRaceid == mType->info.raceid) { + const auto charm = g_iobestiary().getBestiaryCharm(CHARM_LOW); + if (charm) { + chance += charm->percent; + g_game().sendDoubleSoundEffect(target->getPosition(), charm->soundCastEffect, charm->soundImpactEffect, caster); + } + } + } + } + } else if (monster) { + chance = monster->critChance(); + } + + multiplier += damage.criticalDamage; + multiplier = 1 + multiplier / 100; + chance += (uint16_t)damage.criticalChance; + + if (chance != 0 && uniform_random(1, 100) <= chance) { + damage.critical = true; + damage.primary.value *= multiplier; + damage.secondary.value *= multiplier; + } + + if (player) { + // Fatal hit (onslaught) + if (auto playerWeapon = player->getInventoryItem(CONST_SLOT_LEFT); + playerWeapon != nullptr && playerWeapon->getTier() > 0) { + double_t fatalChance = playerWeapon->getFatalChance(); + double_t randomChance = uniform_random(0, 10000) / 100; + if (fatalChance > 0 && randomChance < fatalChance) { + damage.fatal = true; + damage.primary.value += static_cast(std::round(damage.primary.value * 0.6)); + damage.secondary.value += static_cast(std::round(damage.secondary.value * 0.6)); + } + } + } else if (monster) { + damage.primary.value *= monster->getAttackMultiplier(); + damage.secondary.value *= monster->getAttackMultiplier(); + } +} diff --git a/src/creatures/combat/combat.hpp b/src/creatures/combat/combat.hpp index 88c2db31312..2bb2d0a3589 100644 --- a/src/creatures/combat/combat.hpp +++ b/src/creatures/combat/combat.hpp @@ -21,8 +21,6 @@ class Spell; class Player; class MatrixArea; -static const std::unique_ptr &MatrixAreaNull {}; - // for luascript callback class ValueCallback final : public CallBack { public: @@ -247,15 +245,10 @@ class AreaCombat { } } - auto it = areas.find(dir); - if (it == areas.end()) { - return MatrixAreaNull; - } - - return it->second; + return areas[dir]; } - std::map> areas; + std::array, Direction::DIRECTION_LAST + 1> areas {}; bool hasExtArea = false; }; @@ -267,6 +260,8 @@ class Combat { Combat(const Combat &) = delete; Combat &operator=(const Combat &) = delete; + static void applyExtensions(std::shared_ptr caster, std::shared_ptr target, CombatDamage &damage, const CombatParams ¶ms); + static void doCombatHealth(std::shared_ptr caster, std::shared_ptr target, CombatDamage &damage, const CombatParams ¶ms); static void doCombatHealth(std::shared_ptr caster, const Position &position, const std::unique_ptr &area, CombatDamage &damage, const CombatParams ¶ms); diff --git a/src/creatures/monsters/monster.cpp b/src/creatures/monsters/monster.cpp index 4ef06634933..0ce9432ea68 100644 --- a/src/creatures/monsters/monster.cpp +++ b/src/creatures/monsters/monster.cpp @@ -14,7 +14,6 @@ #include "creatures/players/wheel/player_wheel.hpp" #include "game/game.hpp" #include "game/scheduling/dispatcher.hpp" -#include "lua/creature/events.hpp" #include "lua/callbacks/event_callback.hpp" #include "lua/callbacks/events_callbacks.hpp" #include "map/spectators.hpp" @@ -812,12 +811,6 @@ void Monster::doAttacking(uint32_t interval) { bool resetTicks = interval != 0; attackTicks += interval; - float forgeAttackBonus = 0; - if (monsterForgeClassification > ForgeClassifications_t::FORGE_NORMAL_MONSTER) { - uint16_t damageBase = 3; - forgeAttackBonus = static_cast(damageBase + 100) / 100.f; - } - const Position &myPos = getPosition(); const Position &targetPos = attackedCreature->getPosition(); @@ -835,20 +828,8 @@ void Monster::doAttacking(uint32_t interval) { updateLook = false; } - float multiplier; - if (maxCombatValue > 0) { // Defense - multiplier = getDefenseMultiplier(); - } else { // Attack - multiplier = getAttackMultiplier(); - } - - minCombatValue = spellBlock.minCombatValue * multiplier; - maxCombatValue = spellBlock.maxCombatValue * multiplier; - - if (maxCombatValue <= 0 && forgeAttackBonus > 0) { - minCombatValue *= static_cast(forgeAttackBonus); - maxCombatValue *= static_cast(forgeAttackBonus); - } + minCombatValue = spellBlock.minCombatValue; + maxCombatValue = spellBlock.maxCombatValue; if (spellBlock.spell == nullptr) { continue; @@ -1913,15 +1894,8 @@ bool Monster::getCombatValues(int32_t &min, int32_t &max) { return false; } - float multiplier; - if (maxCombatValue > 0) { // Defense - multiplier = getDefenseMultiplier(); - } else { // Attack - multiplier = getAttackMultiplier(); - } - - min = minCombatValue * multiplier; - max = maxCombatValue * multiplier; + min = minCombatValue; + max = maxCombatValue; return true; } diff --git a/src/creatures/monsters/monster.hpp b/src/creatures/monsters/monster.hpp index 5f589af0e28..858b3ac8dd8 100644 --- a/src/creatures/monsters/monster.hpp +++ b/src/creatures/monsters/monster.hpp @@ -77,13 +77,13 @@ class Monster final : public Creature { return mType->info.race; } float getMitigation() const override { - return mType->info.mitigation; + return mType->info.mitigation * getDefenseMultiplier(); } int32_t getArmor() const override { - return mType->info.armor; + return mType->info.armor * getDefenseMultiplier(); } int32_t getDefense() const override { - return mType->info.defense; + return mType->info.defense * getDefenseMultiplier(); } Faction_t getFaction() const override { @@ -126,6 +126,9 @@ class Monster final : public Creature { bool canSeeInvisibility() const override { return isImmune(CONDITION_INVISIBLE); } + uint16_t critChance() const { + return mType->info.critChance; + } uint32_t getManaCost() const { return mType->info.manaCost; } @@ -325,6 +328,16 @@ class Monster final : public Creature { bool isImmune(ConditionType_t conditionType) const override; bool isImmune(CombatType_t combatType) const override; + float getAttackMultiplier() const { + float multiplier = mType->getAttackMultiplier(); + return multiplier * std::pow(1.03f, getForgeStack()); + } + + float getDefenseMultiplier() const { + float multiplier = mType->getDefenseMultiplier(); + return multiplier * std::pow(1.01f, getForgeStack()); + } + private: CreatureWeakHashMap friendList; CreatureIDList targetIDList; @@ -436,14 +449,4 @@ class Monster final : public Creature { void doRandomStep(Direction &nextDirection, bool &result); void onConditionStatusChange(const ConditionType_t &type); - - float getAttackMultiplier() const { - float multiplier = mType->getAttackMultiplier(); - return multiplier * std::pow(1.03f, getForgeStack()); - } - - float getDefenseMultiplier() const { - float multiplier = mType->getAttackMultiplier(); - return multiplier * std::pow(1.01f, getForgeStack()); - } }; diff --git a/src/creatures/monsters/monsters.hpp b/src/creatures/monsters/monsters.hpp index a13792fd297..b214b478e3b 100644 --- a/src/creatures/monsters/monsters.hpp +++ b/src/creatures/monsters/monsters.hpp @@ -128,6 +128,7 @@ class MonsterType { int32_t changeTargetChance = 0; int32_t defense = 0; int32_t armor = 0; + uint16_t critChance = 0; int32_t strategiesTargetNearest = 0; int32_t strategiesTargetHealth = 0; int32_t strategiesTargetDamage = 0; diff --git a/src/creatures/npcs/npcs.cpp b/src/creatures/npcs/npcs.cpp index 432b0adbe15..c18897d1c4c 100644 --- a/src/creatures/npcs/npcs.cpp +++ b/src/creatures/npcs/npcs.cpp @@ -11,7 +11,6 @@ #include "declarations.hpp" #include "creatures/combat/combat.hpp" -#include "creatures/creature.hpp" #include "lua/scripts/lua_environment.hpp" #include "creatures/combat/spells.hpp" #include "creatures/npcs/npcs.hpp" diff --git a/src/creatures/players/player.cpp b/src/creatures/players/player.cpp index 59b9292662d..0ec4bedf8a4 100644 --- a/src/creatures/players/player.cpp +++ b/src/creatures/players/player.cpp @@ -4222,7 +4222,7 @@ void Player::doAttacking(uint32_t) { bool result = false; std::shared_ptr tool = getWeapon(); - const Weapon* weapon = g_weapons().getWeapon(tool); + const WeaponShared_ptr weapon = g_weapons().getWeapon(tool); uint32_t delay = getAttackSpeed(); bool classicSpeed = g_configManager().getBoolean(CLASSIC_ATTACK_SPEED); diff --git a/src/game/game.cpp b/src/game/game.cpp index 88264725b41..9f853ab6b22 100644 --- a/src/game/game.cpp +++ b/src/game/game.cpp @@ -12,13 +12,11 @@ #include "lua/creature/actions.hpp" #include "items/bed.hpp" #include "creatures/creature.hpp" -#include "lua/creature/creatureevent.hpp" #include "database/databasetasks.hpp" #include "lua/creature/events.hpp" #include "lua/callbacks/event_callback.hpp" #include "lua/callbacks/events_callbacks.hpp" #include "game/game.hpp" -#include "game/functions/game_reload.hpp" #include "game/zones/zone.hpp" #include "lua/global/globalevent.hpp" #include "io/iologindata.hpp" @@ -34,13 +32,9 @@ #include "creatures/combat/spells.hpp" #include "lua/creature/talkaction.hpp" #include "items/weapons/weapons.hpp" -#include "lua/scripts/scripts.hpp" -#include "lua/modules/modules.hpp" #include "creatures/players/imbuements/imbuements.hpp" -#include "account/account.hpp" #include "creatures/players/wheel/player_wheel.hpp" #include "creatures/npcs/npc.hpp" -#include "creatures/npcs/npcs.hpp" #include "server/network/webhook/webhook.hpp" #include "protobuf/appearances.pb.h" #include "server/network/protocol/protocollogin.hpp" diff --git a/src/game/scheduling/events_scheduler.cpp b/src/game/scheduling/events_scheduler.cpp index f7bd197979e..d5c71378f4a 100644 --- a/src/game/scheduling/events_scheduler.cpp +++ b/src/game/scheduling/events_scheduler.cpp @@ -12,7 +12,6 @@ #include "config/configmanager.hpp" #include "game/scheduling/events_scheduler.hpp" #include "lua/scripts/scripts.hpp" -#include "utils/pugicast.hpp" bool EventsScheduler::loadScheduleEventFromXml() { pugi::xml_document doc; diff --git a/src/game/zones/zone.cpp b/src/game/zones/zone.cpp index e06975ff7a6..f1aa300efee 100644 --- a/src/game/zones/zone.cpp +++ b/src/game/zones/zone.cpp @@ -14,7 +14,6 @@ #include "creatures/monsters/monster.hpp" #include "creatures/npcs/npc.hpp" #include "creatures/players/player.hpp" -#include "game/scheduling/dispatcher.hpp" phmap::parallel_flat_hash_map> Zone::zones = {}; const static std::shared_ptr nullZone = nullptr; diff --git a/src/io/iologindata.cpp b/src/io/iologindata.cpp index 307d41a9cb3..f32b90568a4 100644 --- a/src/io/iologindata.cpp +++ b/src/io/iologindata.cpp @@ -15,7 +15,6 @@ #include "game/game.hpp" #include "creatures/monsters/monster.hpp" #include "creatures/players/wheel/player_wheel.hpp" -#include "io/ioprey.hpp" bool IOLoginData::gameWorldAuthentication(const std::string &accountDescriptor, const std::string &password, std::string &characterName, uint32_t &accountId, bool oldProtocol) { account::Account account(accountDescriptor); diff --git a/src/io/ioprey.cpp b/src/io/ioprey.cpp index b81dad1fdf7..50c3070b4a0 100644 --- a/src/io/ioprey.cpp +++ b/src/io/ioprey.cpp @@ -9,7 +9,6 @@ #include "pch.hpp" -#include "declarations.hpp" #include "creatures/monsters/monster.hpp" #include "creatures/players/player.hpp" #include "config/configmanager.hpp" diff --git a/src/items/item.cpp b/src/items/item.cpp index ea04be89385..4677041e777 100644 --- a/src/items/item.cpp +++ b/src/items/item.cpp @@ -10,7 +10,6 @@ #include "pch.hpp" #include "items/item.hpp" -#include "items/functions/item/item_parse.hpp" #include "items/containers/container.hpp" #include "items/decay/decay.hpp" #include "game/movement/teleport.hpp" @@ -186,7 +185,7 @@ Item::Item(const uint16_t itemId, uint16_t itemCount /*= 0*/) : const ItemType &it = items[id]; auto itemCharges = it.charges; if (it.isFluidContainer() || it.isSplash()) { - setAttribute(ItemAttribute_t::FLUIDTYPE, itemCount); + setAttribute(ItemAttribute_t::FLUIDTYPE, itemCount * (itemCount < sizeof(Fluids_t))); } else if (it.stackable) { if (itemCount != 0) { setItemCount(static_cast(itemCount)); diff --git a/src/items/items.cpp b/src/items/items.cpp index ca8e20e5b30..690e01a5b92 100644 --- a/src/items/items.cpp +++ b/src/items/items.cpp @@ -11,7 +11,6 @@ #include "items/functions/item/item_parse.hpp" #include "items/items.hpp" -#include "items/weapons/weapons.hpp" #include "game/game.hpp" #include "utils/pugicast.hpp" diff --git a/src/items/tile.cpp b/src/items/tile.cpp index 25f7f865688..0d9a5db0ead 100644 --- a/src/items/tile.cpp +++ b/src/items/tile.cpp @@ -19,7 +19,6 @@ #include "lua/creature/movement.hpp" #include "game/movement/teleport.hpp" #include "items/trashholder.hpp" -#include "map/house/housetile.hpp" #include "io/iomap.hpp" #include "map/spectators.hpp" diff --git a/src/items/weapons/weapons.cpp b/src/items/weapons/weapons.cpp index 995b71518c0..08f1d75c032 100644 --- a/src/items/weapons/weapons.cpp +++ b/src/items/weapons/weapons.cpp @@ -17,7 +17,7 @@ Weapons::Weapons() = default; Weapons::~Weapons() = default; -const Weapon* Weapons::getWeapon(std::shared_ptr item) const { +const WeaponShared_ptr Weapons::getWeapon(std::shared_ptr item) const { if (!item) { return nullptr; } @@ -33,7 +33,7 @@ void Weapons::clear() { weapons.clear(); } -bool Weapons::registerLuaEvent(Weapon* event) { +bool Weapons::registerLuaEvent(WeaponShared_ptr event) { weapons[event->getID()] = event; return true; } @@ -524,7 +524,7 @@ bool WeaponDistance::useWeapon(std::shared_ptr player, std::shared_ptr mainWeaponItem = player->getWeapon(true); - const Weapon* mainWeapon = g_weapons().getWeapon(mainWeaponItem); + const WeaponShared_ptr mainWeapon = g_weapons().getWeapon(mainWeaponItem); if (mainWeapon) { damageModifier = mainWeapon->playerWeaponCheck(player, target, mainWeaponItem->getShootRange()); } else { diff --git a/src/items/weapons/weapons.hpp b/src/items/weapons/weapons.hpp index 90785983e17..78a7195fb3c 100644 --- a/src/items/weapons/weapons.hpp +++ b/src/items/weapons/weapons.hpp @@ -21,7 +21,8 @@ class WeaponMelee; class WeaponDistance; class WeaponWand; -using Weapon_ptr = std::unique_ptr; +using WeaponUnique_ptr = std::unique_ptr; +using WeaponShared_ptr = std::shared_ptr; class Weapons final : public Scripts { public: @@ -36,16 +37,16 @@ class Weapons final : public Scripts { return inject(); } - const Weapon* getWeapon(std::shared_ptr item) const; + const WeaponShared_ptr getWeapon(std::shared_ptr item) const; static int32_t getMaxMeleeDamage(int32_t attackSkill, int32_t attackValue); static int32_t getMaxWeaponDamage(uint32_t level, int32_t attackSkill, int32_t attackValue, float attackFactor, bool isMelee); - bool registerLuaEvent(Weapon* event); + bool registerLuaEvent(WeaponShared_ptr event); void clear(); private: - std::map weapons; + std::map weapons; }; constexpr auto g_weapons = Weapons::getInstance; diff --git a/src/kv/kv.cpp b/src/kv/kv.cpp index cd2a8b974b5..e5dbc974b76 100644 --- a/src/kv/kv.cpp +++ b/src/kv/kv.cpp @@ -11,7 +11,6 @@ #include "kv/kv.hpp" #include "lib/di/container.hpp" -#include "utils/tools.hpp" KVStore &KVStore::getInstance() { return inject(); diff --git a/src/kv/value_wrapper.hpp b/src/kv/value_wrapper.hpp index 9317eb6b8fd..a4e899adcb0 100644 --- a/src/kv/value_wrapper.hpp +++ b/src/kv/value_wrapper.hpp @@ -179,7 +179,10 @@ inline bool operator==(const ValueVariant &lhs, const ValueVariant &rhs) { return b.contains(key) && value.get() == b.at(key).get(); }); } - return a == b; + // Compares a and b if types A and B are the same, at compile-time + if constexpr (std::is_same_v) { + return a == b; + } }, lhs, rhs ); diff --git a/src/lua/callbacks/event_callback.cpp b/src/lua/callbacks/event_callback.cpp index 6444446bde9..8510502b226 100644 --- a/src/lua/callbacks/event_callback.cpp +++ b/src/lua/callbacks/event_callback.cpp @@ -11,8 +11,6 @@ #include "lua/callbacks/event_callback.hpp" -#include "lua/callbacks/event_callback.hpp" -#include "lua/callbacks/events_callbacks.hpp" #include "utils/tools.hpp" #include "items/item.hpp" #include "creatures/players/player.hpp" diff --git a/src/lua/functions/core/game/config_functions.cpp b/src/lua/functions/core/game/config_functions.cpp index a64f1d91b66..bdeaa226fc1 100644 --- a/src/lua/functions/core/game/config_functions.cpp +++ b/src/lua/functions/core/game/config_functions.cpp @@ -251,6 +251,8 @@ void ConfigFunctions::init(lua_State* L) { registerEnumIn(L, "configKeys", VIP_FAMILIAR_TIME_COOLDOWN_REDUCTION); registerEnumIn(L, "configKeys", TOGGLE_HOUSE_TRANSFER_ON_SERVER_RESTART); + + registerEnumIn(L, "configKeys", TOGGLE_RECEIVE_REWARD); #undef registerEnumIn } diff --git a/src/lua/functions/core/game/game_functions.cpp b/src/lua/functions/core/game/game_functions.cpp index 86358f1daf7..ec59b8b1c34 100644 --- a/src/lua/functions/core/game/game_functions.cpp +++ b/src/lua/functions/core/game/game_functions.cpp @@ -23,7 +23,6 @@ #include "lua/creature/talkaction.hpp" #include "lua/functions/creatures/npc/npc_type_functions.hpp" #include "lua/scripts/lua_environment.hpp" -#include "lua/scripts/scripts.hpp" #include "lua/creature/events.hpp" #include "lua/callbacks/event_callback.hpp" #include "lua/callbacks/events_callbacks.hpp" diff --git a/src/lua/functions/core/game/lua_enums.cpp b/src/lua/functions/core/game/lua_enums.cpp index 8d86185290f..fc1586f3363 100644 --- a/src/lua/functions/core/game/lua_enums.cpp +++ b/src/lua/functions/core/game/lua_enums.cpp @@ -11,15 +11,12 @@ #include "lua/functions/core/game/lua_enums.hpp" -#include "account/account.hpp" #include "creatures/players/wheel/wheel_definitions.hpp" #include "io/io_bosstiary.hpp" #include "config/configmanager.hpp" #include "creatures/creature.hpp" -#include "lua/creature/creatureevent.hpp" #include "declarations.hpp" #include "game/functions/game_reload.hpp" -#include "game/game.hpp" #define registerEnumClass(luaState, enumClassType) \ { \ diff --git a/src/lua/functions/creatures/monster/monster_type_functions.cpp b/src/lua/functions/creatures/monster/monster_type_functions.cpp index 1beea8de66b..ba77c49a90a 100644 --- a/src/lua/functions/creatures/monster/monster_type_functions.cpp +++ b/src/lua/functions/creatures/monster/monster_type_functions.cpp @@ -280,6 +280,20 @@ int MonsterTypeFunctions::luaMonsterTypeCanPushCreatures(lua_State* L) { return 1; } +int MonsterTypeFunctions::luaMonsterTypeCritChance(lua_State* L) { + // get: monsterType:critChance() set: monsterType:critChance(int) + const auto monsterType = getUserdataShared(L, 1); + if (monsterType) { + if (lua_gettop(L) == 2) { + monsterType->info.critChance = getNumber(L, 2); + } + lua_pushnumber(L, monsterType->info.critChance); + } else { + lua_pushnil(L); + } + return 1; +} + int32_t MonsterTypeFunctions::luaMonsterTypeName(lua_State* L) { // get: monsterType:name() set: monsterType:name(name) const auto monsterType = getUserdataShared(L, 1); diff --git a/src/lua/functions/creatures/monster/monster_type_functions.hpp b/src/lua/functions/creatures/monster/monster_type_functions.hpp index d9c513d2bce..9d892219250 100644 --- a/src/lua/functions/creatures/monster/monster_type_functions.hpp +++ b/src/lua/functions/creatures/monster/monster_type_functions.hpp @@ -35,6 +35,8 @@ class MonsterTypeFunctions final : LuaScriptInterface { registerMethod(L, "MonsterType", "canPushItems", MonsterTypeFunctions::luaMonsterTypeCanPushItems); registerMethod(L, "MonsterType", "canPushCreatures", MonsterTypeFunctions::luaMonsterTypeCanPushCreatures); + registerMethod(L, "MonsterType", "critChance", MonsterTypeFunctions::luaMonsterTypeCritChance); + registerMethod(L, "MonsterType", "name", MonsterTypeFunctions::luaMonsterTypeName); registerMethod(L, "MonsterType", "nameDescription", MonsterTypeFunctions::luaMonsterTypeNameDescription); @@ -260,10 +262,5 @@ class MonsterTypeFunctions final : LuaScriptInterface { static int luaMonsterTypeAddSound(lua_State* L); static int luaMonsterTypeGetSounds(lua_State* L); static int luaMonsterTypedeathSound(lua_State* L); - - // Hazard system - static int luaMonsterTypeHazardSystemCrit(lua_State* L); - static int luaMonsterTypeHazardSystemDodge(lua_State* L); - static int luaMonsterTypeHazardSystemSpawnPod(lua_State* L); - static int luaMonsterTypeHazardSystemDamageBoost(lua_State* L); + static int luaMonsterTypeCritChance(lua_State* L); }; diff --git a/src/lua/functions/items/imbuement_functions.cpp b/src/lua/functions/items/imbuement_functions.cpp index f512e56a62b..2a4e85d7d88 100644 --- a/src/lua/functions/items/imbuement_functions.cpp +++ b/src/lua/functions/items/imbuement_functions.cpp @@ -9,7 +9,6 @@ #include "pch.hpp" -#include "items/item.hpp" #include "items/weapons/weapons.hpp" #include "creatures/players/imbuements/imbuements.hpp" #include "lua/functions/items/imbuement_functions.hpp" diff --git a/src/lua/functions/items/weapon_functions.cpp b/src/lua/functions/items/weapon_functions.cpp index 2e5fde7ff15..3a41d0ac75d 100644 --- a/src/lua/functions/items/weapon_functions.cpp +++ b/src/lua/functions/items/weapon_functions.cpp @@ -25,7 +25,7 @@ int WeaponFunctions::luaCreateWeapon(lua_State* L) { case WEAPON_AXE: case WEAPON_CLUB: { if (auto weaponPtr = g_luaEnvironment().createWeaponObject(getScriptEnv()->getScriptInterface())) { - pushUserdata(L, weaponPtr.get()); + pushUserdata(L, weaponPtr); setMetatable(L, -1, "Weapon"); weaponPtr->weaponType = type; } else { @@ -37,7 +37,7 @@ int WeaponFunctions::luaCreateWeapon(lua_State* L) { case WEAPON_DISTANCE: case WEAPON_AMMO: { if (auto weaponPtr = g_luaEnvironment().createWeaponObject(getScriptEnv()->getScriptInterface())) { - pushUserdata(L, weaponPtr.get()); + pushUserdata(L, weaponPtr); setMetatable(L, -1, "Weapon"); weaponPtr->weaponType = type; } else { @@ -47,7 +47,7 @@ int WeaponFunctions::luaCreateWeapon(lua_State* L) { } case WEAPON_WAND: { if (auto weaponPtr = g_luaEnvironment().createWeaponObject(getScriptEnv()->getScriptInterface())) { - pushUserdata(L, weaponPtr.get()); + pushUserdata(L, weaponPtr); setMetatable(L, -1, "Weapon"); weaponPtr->weaponType = type; } else { @@ -65,7 +65,7 @@ int WeaponFunctions::luaCreateWeapon(lua_State* L) { int WeaponFunctions::luaWeaponAction(lua_State* L) { // weapon:action(callback) - Weapon* weapon = getUserdata(L, 1); + const WeaponShared_ptr &weapon = getUserdataShared(L, 1); if (weapon) { std::string typeName = getString(L, 2); std::string tmpStr = asLowerCaseString(typeName); @@ -90,15 +90,15 @@ int WeaponFunctions::luaWeaponAction(lua_State* L) { int WeaponFunctions::luaWeaponRegister(lua_State* L) { // weapon:register() - Weapon** weaponPtr = getRawUserdata(L, 1); + WeaponShared_ptr* weaponPtr = getRawUserDataShared(L, 1); if (weaponPtr && *weaponPtr) { - Weapon* weapon = *weaponPtr; + WeaponShared_ptr weapon = *weaponPtr; if (weapon->weaponType == WEAPON_DISTANCE || weapon->weaponType == WEAPON_AMMO || weapon->weaponType == WEAPON_MISSILE) { - weapon = getUserdata(L, 1); + weapon = getUserdataShared(L, 1); } else if (weapon->weaponType == WEAPON_WAND) { - weapon = getUserdata(L, 1); + weapon = getUserdataShared(L, 1); } else { - weapon = getUserdata(L, 1); + weapon = getUserdataShared(L, 1); } uint16_t id = weapon->getID(); @@ -123,7 +123,7 @@ int WeaponFunctions::luaWeaponRegister(lua_State* L) { int WeaponFunctions::luaWeaponOnUseWeapon(lua_State* L) { // weapon:onUseWeapon(callback) - Weapon* weapon = getUserdata(L, 1); + const WeaponShared_ptr &weapon = getUserdataShared(L, 1); if (weapon) { if (!weapon->loadCallback()) { pushBoolean(L, false); @@ -139,7 +139,7 @@ int WeaponFunctions::luaWeaponOnUseWeapon(lua_State* L) { int WeaponFunctions::luaWeaponUnproperly(lua_State* L) { // weapon:wieldedUnproperly(bool) - Weapon* weapon = getUserdata(L, 1); + const WeaponShared_ptr &weapon = getUserdataShared(L, 1); if (weapon) { weapon->setWieldUnproperly(getBoolean(L, 2)); pushBoolean(L, true); @@ -151,7 +151,7 @@ int WeaponFunctions::luaWeaponUnproperly(lua_State* L) { int WeaponFunctions::luaWeaponLevel(lua_State* L) { // weapon:level(lvl) - Weapon* weapon = getUserdata(L, 1); + const WeaponShared_ptr &weapon = getUserdataShared(L, 1); if (weapon) { weapon->setRequiredLevel(getNumber(L, 2)); weapon->setWieldInfo(WIELDINFO_LEVEL); @@ -164,7 +164,7 @@ int WeaponFunctions::luaWeaponLevel(lua_State* L) { int WeaponFunctions::luaWeaponMagicLevel(lua_State* L) { // weapon:magicLevel(lvl) - Weapon* weapon = getUserdata(L, 1); + const WeaponShared_ptr &weapon = getUserdataShared(L, 1); if (weapon) { weapon->setRequiredMagLevel(getNumber(L, 2)); weapon->setWieldInfo(WIELDINFO_MAGLV); @@ -177,7 +177,7 @@ int WeaponFunctions::luaWeaponMagicLevel(lua_State* L) { int WeaponFunctions::luaWeaponMana(lua_State* L) { // weapon:mana(mana) - Weapon* weapon = getUserdata(L, 1); + const WeaponShared_ptr &weapon = getUserdataShared(L, 1); if (weapon) { weapon->setMana(getNumber(L, 2)); pushBoolean(L, true); @@ -189,7 +189,7 @@ int WeaponFunctions::luaWeaponMana(lua_State* L) { int WeaponFunctions::luaWeaponManaPercent(lua_State* L) { // weapon:manaPercent(percent) - Weapon* weapon = getUserdata(L, 1); + const WeaponShared_ptr &weapon = getUserdataShared(L, 1); if (weapon) { weapon->setManaPercent(getNumber(L, 2)); pushBoolean(L, true); @@ -201,7 +201,7 @@ int WeaponFunctions::luaWeaponManaPercent(lua_State* L) { int WeaponFunctions::luaWeaponHealth(lua_State* L) { // weapon:health(health) - Weapon* weapon = getUserdata(L, 1); + const WeaponShared_ptr &weapon = getUserdataShared(L, 1); if (weapon) { weapon->setHealth(getNumber(L, 2)); pushBoolean(L, true); @@ -213,7 +213,7 @@ int WeaponFunctions::luaWeaponHealth(lua_State* L) { int WeaponFunctions::luaWeaponHealthPercent(lua_State* L) { // weapon:healthPercent(percent) - Weapon* weapon = getUserdata(L, 1); + const WeaponShared_ptr &weapon = getUserdataShared(L, 1); if (weapon) { weapon->setHealthPercent(getNumber(L, 2)); pushBoolean(L, true); @@ -225,7 +225,7 @@ int WeaponFunctions::luaWeaponHealthPercent(lua_State* L) { int WeaponFunctions::luaWeaponSoul(lua_State* L) { // weapon:soul(soul) - Weapon* weapon = getUserdata(L, 1); + const WeaponShared_ptr &weapon = getUserdataShared(L, 1); if (weapon) { weapon->setSoul(getNumber(L, 2)); pushBoolean(L, true); @@ -237,7 +237,7 @@ int WeaponFunctions::luaWeaponSoul(lua_State* L) { int WeaponFunctions::luaWeaponBreakChance(lua_State* L) { // weapon:breakChance(percent) - Weapon* weapon = getUserdata(L, 1); + const WeaponShared_ptr &weapon = getUserdataShared(L, 1); if (weapon) { weapon->setBreakChance(getNumber(L, 2)); pushBoolean(L, true); @@ -249,7 +249,7 @@ int WeaponFunctions::luaWeaponBreakChance(lua_State* L) { int WeaponFunctions::luaWeaponWandDamage(lua_State* L) { // weapon:damage(damage[min, max]) only use this if the weapon is a wand! - WeaponWand* weapon = getUserdata(L, 1); + const auto &weapon = getUserdataShared(L, 1); if (weapon) { weapon->setMinChange(getNumber(L, 2)); if (lua_gettop(L) > 2) { @@ -266,7 +266,7 @@ int WeaponFunctions::luaWeaponWandDamage(lua_State* L) { int WeaponFunctions::luaWeaponElement(lua_State* L) { // weapon:element(combatType) - Weapon* weapon = getUserdata(L, 1); + const WeaponShared_ptr &weapon = getUserdataShared(L, 1); if (weapon) { if (!getNumber(L, 2)) { std::string element = getString(L, 2); @@ -300,7 +300,7 @@ int WeaponFunctions::luaWeaponElement(lua_State* L) { int WeaponFunctions::luaWeaponPremium(lua_State* L) { // weapon:premium(bool) - Weapon* weapon = getUserdata(L, 1); + const WeaponShared_ptr &weapon = getUserdataShared(L, 1); if (weapon) { weapon->setNeedPremium(getBoolean(L, 2)); weapon->setWieldInfo(WIELDINFO_PREMIUM); @@ -313,7 +313,7 @@ int WeaponFunctions::luaWeaponPremium(lua_State* L) { int WeaponFunctions::luaWeaponVocation(lua_State* L) { // weapon:vocation(vocName[, showInDescription = false, lastVoc = false]) - Weapon* weapon = getUserdata(L, 1); + const WeaponShared_ptr &weapon = getUserdataShared(L, 1); if (weapon) { weapon->addVocWeaponMap(getString(L, 2)); weapon->setWieldInfo(WIELDINFO_VOCREQ); @@ -352,7 +352,7 @@ int WeaponFunctions::luaWeaponVocation(lua_State* L) { int WeaponFunctions::luaWeaponId(lua_State* L) { // weapon:id(id) - Weapon* weapon = getUserdata(L, 1); + const WeaponShared_ptr &weapon = getUserdataShared(L, 1); if (weapon) { weapon->setID(getNumber(L, 2)); pushBoolean(L, true); @@ -364,7 +364,7 @@ int WeaponFunctions::luaWeaponId(lua_State* L) { int WeaponFunctions::luaWeaponAttack(lua_State* L) { // weapon:attack(atk) - Weapon* weapon = getUserdata(L, 1); + const WeaponShared_ptr &weapon = getUserdataShared(L, 1); if (weapon) { uint16_t id = weapon->getID(); ItemType &it = Item::items.getItemType(id); @@ -378,7 +378,7 @@ int WeaponFunctions::luaWeaponAttack(lua_State* L) { int WeaponFunctions::luaWeaponDefense(lua_State* L) { // weapon:defense(defense[, extraDefense]) - Weapon* weapon = getUserdata(L, 1); + const WeaponShared_ptr &weapon = getUserdataShared(L, 1); if (weapon) { uint16_t id = weapon->getID(); ItemType &it = Item::items.getItemType(id); @@ -395,7 +395,7 @@ int WeaponFunctions::luaWeaponDefense(lua_State* L) { int WeaponFunctions::luaWeaponRange(lua_State* L) { // weapon:range(range) - Weapon* weapon = getUserdata(L, 1); + const WeaponShared_ptr &weapon = getUserdataShared(L, 1); if (weapon) { uint16_t id = weapon->getID(); ItemType &it = Item::items.getItemType(id); @@ -409,7 +409,7 @@ int WeaponFunctions::luaWeaponRange(lua_State* L) { int WeaponFunctions::luaWeaponCharges(lua_State* L) { // weapon:charges(charges[, showCharges = true]) - Weapon* weapon = getUserdata(L, 1); + const WeaponShared_ptr &weapon = getUserdataShared(L, 1); if (weapon) { bool showCharges = true; if (lua_gettop(L) > 2) { @@ -428,7 +428,7 @@ int WeaponFunctions::luaWeaponCharges(lua_State* L) { int WeaponFunctions::luaWeaponDuration(lua_State* L) { // weapon:duration(duration[, showDuration = true]) - Weapon* weapon = getUserdata(L, 1); + const WeaponShared_ptr &weapon = getUserdataShared(L, 1); if (weapon) { bool showDuration = true; if (lua_gettop(L) > 2) { @@ -447,7 +447,7 @@ int WeaponFunctions::luaWeaponDuration(lua_State* L) { int WeaponFunctions::luaWeaponDecayTo(lua_State* L) { // weapon:decayTo([itemid = 0] - Weapon* weapon = getUserdata(L, 1); + const WeaponShared_ptr &weapon = getUserdataShared(L, 1); if (weapon) { uint16_t itemid = 0; if (lua_gettop(L) > 1) { @@ -465,7 +465,7 @@ int WeaponFunctions::luaWeaponDecayTo(lua_State* L) { int WeaponFunctions::luaWeaponTransformEquipTo(lua_State* L) { // weapon:transformEquipTo(itemid) - Weapon* weapon = getUserdata(L, 1); + const WeaponShared_ptr &weapon = getUserdataShared(L, 1); if (weapon) { uint16_t id = weapon->getID(); ItemType &it = Item::items.getItemType(id); @@ -479,7 +479,7 @@ int WeaponFunctions::luaWeaponTransformEquipTo(lua_State* L) { int WeaponFunctions::luaWeaponTransformDeEquipTo(lua_State* L) { // weapon:transformDeEquipTo(itemid) - Weapon* weapon = getUserdata(L, 1); + const WeaponShared_ptr &weapon = getUserdataShared(L, 1); if (weapon) { uint16_t id = weapon->getID(); ItemType &it = Item::items.getItemType(id); @@ -493,7 +493,7 @@ int WeaponFunctions::luaWeaponTransformDeEquipTo(lua_State* L) { int WeaponFunctions::luaWeaponShootType(lua_State* L) { // weapon:shootType(type) - Weapon* weapon = getUserdata(L, 1); + const WeaponShared_ptr &weapon = getUserdataShared(L, 1); if (weapon) { uint16_t id = weapon->getID(); ItemType &it = Item::items.getItemType(id); @@ -507,7 +507,7 @@ int WeaponFunctions::luaWeaponShootType(lua_State* L) { int WeaponFunctions::luaWeaponSlotType(lua_State* L) { // weapon:slotType(slot) - Weapon* weapon = getUserdata(L, 1); + const WeaponShared_ptr &weapon = getUserdataShared(L, 1); if (weapon) { uint16_t id = weapon->getID(); ItemType &it = Item::items.getItemType(id); @@ -527,7 +527,7 @@ int WeaponFunctions::luaWeaponSlotType(lua_State* L) { int WeaponFunctions::luaWeaponAmmoType(lua_State* L) { // weapon:ammoType(type) - WeaponDistance* weapon = getUserdata(L, 1); + const auto &weapon = getUserdataShared(L, 1); if (weapon) { uint16_t id = weapon->getID(); ItemType &it = Item::items.getItemType(id); @@ -553,7 +553,7 @@ int WeaponFunctions::luaWeaponAmmoType(lua_State* L) { int WeaponFunctions::luaWeaponHitChance(lua_State* L) { // weapon:hitChance(chance) - Weapon* weapon = getUserdata(L, 1); + const WeaponShared_ptr &weapon = getUserdataShared(L, 1); if (weapon) { uint16_t id = weapon->getID(); ItemType &it = Item::items.getItemType(id); @@ -567,7 +567,7 @@ int WeaponFunctions::luaWeaponHitChance(lua_State* L) { int WeaponFunctions::luaWeaponMaxHitChance(lua_State* L) { // weapon:maxHitChance(max) - Weapon* weapon = getUserdata(L, 1); + const WeaponShared_ptr &weapon = getUserdataShared(L, 1); if (weapon) { uint16_t id = weapon->getID(); ItemType &it = Item::items.getItemType(id); @@ -581,34 +581,34 @@ int WeaponFunctions::luaWeaponMaxHitChance(lua_State* L) { int WeaponFunctions::luaWeaponExtraElement(lua_State* L) { // weapon:extraElement(atk, combatType) - Weapon* weapon = getUserdata(L, 1); + const WeaponShared_ptr &weapon = getUserdataShared(L, 1); if (weapon) { uint16_t id = weapon->getID(); ItemType &it = Item::items.getItemType(id); - it.abilities.get()->elementDamage = getNumber(L, 2); + it.abilities->elementDamage = getNumber(L, 2); if (!getNumber(L, 3)) { std::string element = getString(L, 3); std::string tmpStrValue = asLowerCaseString(element); if (tmpStrValue == "earth") { - it.abilities.get()->elementType = COMBAT_EARTHDAMAGE; + it.abilities->elementType = COMBAT_EARTHDAMAGE; } else if (tmpStrValue == "ice") { - it.abilities.get()->elementType = COMBAT_ICEDAMAGE; + it.abilities->elementType = COMBAT_ICEDAMAGE; } else if (tmpStrValue == "energy") { - it.abilities.get()->elementType = COMBAT_ENERGYDAMAGE; + it.abilities->elementType = COMBAT_ENERGYDAMAGE; } else if (tmpStrValue == "fire") { - it.abilities.get()->elementType = COMBAT_FIREDAMAGE; + it.abilities->elementType = COMBAT_FIREDAMAGE; } else if (tmpStrValue == "death") { - it.abilities.get()->elementType = COMBAT_DEATHDAMAGE; + it.abilities->elementType = COMBAT_DEATHDAMAGE; } else if (tmpStrValue == "holy") { - it.abilities.get()->elementType = COMBAT_HOLYDAMAGE; + it.abilities->elementType = COMBAT_HOLYDAMAGE; } else { g_logger().warn("[WeaponFunctions:luaWeaponExtraElement] - " "Type {} does not exist", element); } } else { - it.abilities.get()->elementType = getNumber(L, 3); + it.abilities->elementType = getNumber(L, 3); } pushBoolean(L, true); } else { diff --git a/src/lua/functions/items/weapon_functions.hpp b/src/lua/functions/items/weapon_functions.hpp index 2f0d2e8ccb6..01ba6966317 100644 --- a/src/lua/functions/items/weapon_functions.hpp +++ b/src/lua/functions/items/weapon_functions.hpp @@ -14,7 +14,7 @@ class WeaponFunctions final : LuaScriptInterface { public: static void init(lua_State* L) { - registerClass(L, "Weapon", "", WeaponFunctions::luaCreateWeapon); + registerSharedClass(L, "Weapon", "", WeaponFunctions::luaCreateWeapon); registerMethod(L, "Weapon", "action", WeaponFunctions::luaWeaponAction); registerMethod(L, "Weapon", "register", WeaponFunctions::luaWeaponRegister); registerMethod(L, "Weapon", "id", WeaponFunctions::luaWeaponId); diff --git a/src/lua/functions/lua_functions_loader.cpp b/src/lua/functions/lua_functions_loader.cpp index 944849b1e6f..cf377592988 100644 --- a/src/lua/functions/lua_functions_loader.cpp +++ b/src/lua/functions/lua_functions_loader.cpp @@ -12,13 +12,11 @@ #include "creatures/combat/spells.hpp" #include "creatures/monsters/monster.hpp" #include "creatures/npcs/npc.hpp" -#include "creatures/players/imbuements/imbuements.hpp" #include "creatures/players/player.hpp" #include "creatures/players/grouping/guild.hpp" #include "game/zones/zone.hpp" #include "game/game.hpp" #include "game/movement/teleport.hpp" -#include "items/weapons/weapons.hpp" #include "lua/functions/core/core_functions.hpp" #include "lua/functions/creatures/creature_functions.hpp" #include "lua/functions/events/events_functions.hpp" diff --git a/src/lua/scripts/lua_environment.hpp b/src/lua/scripts/lua_environment.hpp index 216abb8ec78..042a21fe1d8 100644 --- a/src/lua/scripts/lua_environment.hpp +++ b/src/lua/scripts/lua_environment.hpp @@ -25,7 +25,7 @@ class LuaEnvironment : public LuaScriptInterface { static bool shuttingDown; LuaEnvironment(); - ~LuaEnvironment(); + ~LuaEnvironment() override; lua_State* getLuaState() override; @@ -38,7 +38,7 @@ class LuaEnvironment : public LuaScriptInterface { } bool initState() override; - bool reInitState(); + bool reInitState() override; bool closeState() override; LuaScriptInterface* getTestInterface(); @@ -50,7 +50,7 @@ class LuaEnvironment : public LuaScriptInterface { template std::shared_ptr createWeaponObject(LuaScriptInterface* interface) { auto weapon = std::make_shared(interface); - int weaponId = ++lastWeaponId; + auto weaponId = ++lastWeaponId; weaponMap[weaponId] = weapon; weaponIdMap[interface].push_back(weaponId); return weapon; diff --git a/src/lua/scripts/luascript.hpp b/src/lua/scripts/luascript.hpp index 80541e86d18..8f0b3b36c19 100644 --- a/src/lua/scripts/luascript.hpp +++ b/src/lua/scripts/luascript.hpp @@ -23,7 +23,7 @@ class LuaScriptInterface : public LuaFunctionsLoader { LuaScriptInterface &operator=(const LuaScriptInterface &) = delete; virtual bool initState(); - bool reInitState(); + virtual bool reInitState(); int32_t loadFile(const std::string &file, const std::string &scriptName); diff --git a/src/lua/scripts/script_environment.cpp b/src/lua/scripts/script_environment.cpp index 8899a954f69..ccebdb1a8dd 100644 --- a/src/lua/scripts/script_environment.cpp +++ b/src/lua/scripts/script_environment.cpp @@ -9,7 +9,6 @@ #include "pch.hpp" -#include "declarations.hpp" #include "game/game.hpp" #include "lua/scripts/luascript.hpp" #include "lua/scripts/script_environment.hpp" diff --git a/src/map/utils/qtreenode.cpp b/src/map/utils/qtreenode.cpp index 92d0a0423ee..ace469e14aa 100644 --- a/src/map/utils/qtreenode.cpp +++ b/src/map/utils/qtreenode.cpp @@ -10,7 +10,6 @@ #include "pch.hpp" #include "creatures/creature.hpp" -#include "map/mapcache.hpp" #include "qtreenode.hpp" bool QTreeLeafNode::newLeaf = false; diff --git a/src/server/network/connection/connection.cpp b/src/server/network/connection/connection.cpp index 04e7a82a64f..c2df08b2824 100644 --- a/src/server/network/connection/connection.cpp +++ b/src/server/network/connection/connection.cpp @@ -12,7 +12,6 @@ #include "server/network/connection/connection.hpp" #include "server/network/message/outputmessage.hpp" #include "server/network/protocol/protocol.hpp" -#include "server/network/protocol/protocolgame.hpp" #include "game/scheduling/scheduler.hpp" #include "game/scheduling/dispatcher.hpp" #include "server/server.hpp" diff --git a/src/server/network/message/networkmessage.cpp b/src/server/network/message/networkmessage.cpp index 9c7b5a333cb..457e3b32be0 100644 --- a/src/server/network/message/networkmessage.cpp +++ b/src/server/network/message/networkmessage.cpp @@ -11,7 +11,6 @@ #include "server/network/message/networkmessage.hpp" #include "items/containers/container.hpp" -#include "creatures/creature.hpp" int32_t NetworkMessage::decodeHeader() { int32_t newSize = buffer[0] | buffer[1] << 8; diff --git a/src/server/network/protocol/protocolgame.cpp b/src/server/network/protocol/protocolgame.cpp index 2848013701c..59c2867e519 100644 --- a/src/server/network/protocol/protocolgame.cpp +++ b/src/server/network/protocol/protocolgame.cpp @@ -6039,11 +6039,7 @@ void ProtocolGame::sendAllowBugReport() { NetworkMessage msg; msg.addByte(0x1A); - if (player->getAccountType() >= account::ACCOUNT_TYPE_NORMAL) { - msg.addByte(0x01); - } else { - msg.addByte(0x00); - } + msg.addByte(0x00); // 0x01 = DISABLE bug report writeToOutputBuffer(msg); }