diff --git a/data-otservbr-global/scripts/spells/attack/divine_grenade.lua b/data-otservbr-global/scripts/spells/attack/divine_grenade.lua index a2112af4c85..b1dc6399c7d 100644 --- a/data-otservbr-global/scripts/spells/attack/divine_grenade.lua +++ b/data-otservbr-global/scripts/spells/attack/divine_grenade.lua @@ -1,10 +1,12 @@ local combatGrenade = Combat() combatGrenade:setParameter(COMBAT_PARAM_TYPE, COMBAT_HOLYDAMAGE) combatGrenade:setArea(createCombatArea(AREA_CIRCLE2X2)) +combatGrenade:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_HOLYDAMAGE) function onGetFormulaValues(player, level, maglevel) local min = (level / 5) + (maglevel * 4) local max = (level / 5) + (maglevel * 6) + local grade = player:upgradeSpellsWOD("Divine Grenade") local multiplier = 1.0 @@ -15,6 +17,7 @@ function onGetFormulaValues(player, level, maglevel) min = min * multiplier max = max * multiplier + return -min, -max end @@ -37,32 +40,36 @@ local explodeGrenade = function(position, playerId) var.type = 2 -- VARIANT_POSITION var.pos = position combatGrenade:execute(player, var) - player:getPosition():removeMagicEffect(CONST_ME_DIVINE_GRENADE) end -local combatCast = Combat() -combatCast:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_HOLY) +local function removeGrenadeEffect(position) + position:removeMagicEffect(CONST_ME_DIVINE_GRENADE) +end function onTargetCreature(creature, target) - if not creature and target and creature:isPlayer() then + if not (creature and target and creature:isPlayer()) then return false end - local position = target:getPosition() + local position = creature:getPosition():getWithinRange(target:getPosition(), 4) addEvent(explodeGrenade, 3000, position, creature:getId()) + addEvent(removeGrenadeEffect, 3000, position) return true end +local combatCast = Combat() combatCast:setCallback(CALLBACK_PARAM_TARGETCREATURE, "onTargetCreature") local spell = Spell("instant") function spell.onCastSpell(creature, var) - if not (creature and creature:isPlayer()) then + if not creature or not creature:isPlayer() then return false end - local grade = creature:upgradeSpellsWOD("Divine Grenade") - if grade == WHEEL_GRADE_NONE then + + local grade = creature:revelationStageWOD("Divine Grenade") + + if grade == 0 then creature:sendCancelMessage("You cannot cast this spell") creature:getPosition():sendMagicEffect(CONST_ME_POFF) return false @@ -73,7 +80,9 @@ function spell.onCastSpell(creature, var) var.instantName = "Divine Grenade Cast" if combatCast:execute(creature, var) then - creature:getPosition():sendMagicEffect(CONST_ME_DIVINE_GRENADE) + local target = Creature(var:getNumber()) + local position = creature:getPosition():getWithinRange(target:getPosition(), 4) + position:sendMagicEffect(CONST_ME_DIVINE_GRENADE) local condition = Condition(CONDITION_SPELLCOOLDOWN, CONDITIONID_DEFAULT, 258) condition:setTicks((cooldown * 1000) / configManager.getFloat(configKeys.RATE_SPELL_COOLDOWN)) creature:addCondition(condition) diff --git a/data/libs/functions/position.lua b/data/libs/functions/position.lua index 2ba38968f5f..27923eeb268 100644 --- a/data/libs/functions/position.lua +++ b/data/libs/functions/position.lua @@ -49,7 +49,6 @@ function Position:moveUpstairs() return self end --- Functions from OTServBR-Global function Position:isInRange(from, to) -- No matter what corner from and to is, we want to make -- life easier by calculating north-west and south-east @@ -373,3 +372,20 @@ function Position:isProtectionZoneTile() end return tile:hasFlag(TILESTATE_PROTECTIONZONE) end + +--- Calculates and returns a position based on a specified range. +-- This method determines which position (self or the other) is returned based on the provided range. +-- If the distance between self and the other position is greater than the specified range, +-- it returns the self position. Otherwise, it returns the other position. +-- @param self The position object calling the method. +-- @param otherPosition Position The other position to compare with. +-- @param range number The range to compare the distance against. +-- @return Position The position within the specified range (either self or otherPosition). +function Position.getWithinRange(self, otherPosition, range) + local distance = math.max(math.abs(self.x - otherPosition.x), math.abs(self.y - otherPosition.y)) + if distance > range then + return self + end + + return otherPosition +end diff --git a/src/lua/functions/core/game/bank_functions.cpp b/src/lua/functions/core/game/bank_functions.cpp index 90e4fdecb5f..f6732b8bf70 100644 --- a/src/lua/functions/core/game/bank_functions.cpp +++ b/src/lua/functions/core/game/bank_functions.cpp @@ -7,7 +7,7 @@ int BankFunctions::luaBankCredit(lua_State* L) { // Bank.credit(playerOrGuild, amount) auto bank = getBank(L, 1); if (bank == nullptr) { - lua_pushnil(L); + reportErrorFunc("Bank is nullptr"); return 1; } uint64_t amount = getNumber(L, 2); @@ -19,7 +19,7 @@ int BankFunctions::luaBankDebit(lua_State* L) { // Bank.debit(playerOrGuild, amount) auto bank = getBank(L, 1); if (bank == nullptr) { - lua_pushnil(L); + reportErrorFunc("Bank is nullptr"); return 1; } uint64_t amount = getNumber(L, 2); @@ -31,7 +31,7 @@ int BankFunctions::luaBankBalance(lua_State* L) { // Bank.balance(playerOrGuild[, amount]]) auto bank = getBank(L, 1); if (bank == nullptr) { - lua_pushnil(L); + reportErrorFunc("Bank is nullptr"); return 1; } if (lua_gettop(L) == 1) { @@ -47,7 +47,7 @@ int BankFunctions::luaBankHasBalance(lua_State* L) { // Bank.hasBalance(playerOrGuild, amount) auto bank = getBank(L, 1); if (bank == nullptr) { - lua_pushnil(L); + reportErrorFunc("Bank is nullptr"); return 1; } uint64_t amount = getNumber(L, 2); @@ -60,13 +60,13 @@ int BankFunctions::luaBankTransfer(lua_State* L) { auto source = getBank(L, 1); if (source == nullptr) { g_logger().debug("BankFunctions::luaBankTransfer: source is null"); - lua_pushnil(L); + reportErrorFunc("Bank is nullptr"); return 1; } std::shared_ptr destination = getBank(L, 2); if (destination == nullptr) { g_logger().debug("BankFunctions::luaBankTransfer: destination is null"); - lua_pushnil(L); + reportErrorFunc("Bank is nullptr"); return 1; } uint64_t amount = getNumber(L, 3); @@ -78,12 +78,12 @@ int BankFunctions::luaBankTransferToGuild(lua_State* L) { // Bank.transfer(fromPlayerOrGuild, toGuild, amount) auto source = getBank(L, 1); if (source == nullptr) { - lua_pushnil(L); + reportErrorFunc("Source is nullptr"); return 1; } std::shared_ptr destination = getBank(L, 2, true /* isGuild */); if (destination == nullptr) { - lua_pushnil(L); + reportErrorFunc("Destination is nullptr"); return 1; } uint64_t amount = getNumber(L, 3); @@ -93,20 +93,21 @@ int BankFunctions::luaBankTransferToGuild(lua_State* L) { int BankFunctions::luaBankWithdraw(lua_State* L) { // Bank.withdraw(player, amount[, source = player]) - auto player = getPlayer(L, 1); + const auto &player = getPlayer(L, 1); + if (!player) { + reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + return 1; + } + uint64_t amount = getNumber(L, 2); if (lua_gettop(L) == 2) { - if (!player) { - return 1; - } - const auto bank = std::make_shared(player); pushBoolean(L, bank->withdraw(player, amount)); return 1; } auto source = getBank(L, 3); if (source == nullptr) { - lua_pushnil(L); + reportErrorFunc("Source is nullptr"); return 1; } pushBoolean(L, source->withdraw(player, amount)); @@ -115,8 +116,9 @@ int BankFunctions::luaBankWithdraw(lua_State* L) { int BankFunctions::luaBankDeposit(lua_State* L) { // Bank.deposit(player, amount[, destination = player]) - auto player = getPlayer(L, 1); + const auto &player = getPlayer(L, 1); if (!player) { + reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); return 1; } const auto bank = std::make_shared(player); @@ -134,7 +136,7 @@ int BankFunctions::luaBankDeposit(lua_State* L) { } auto destination = getBank(L, 3); if (destination == nullptr) { - lua_pushnil(L); + reportErrorFunc("Destination is nullptr"); return 1; } pushBoolean(L, g_game().removeMoney(player, amount) && destination->credit(amount)); diff --git a/src/lua/functions/core/game/global_functions.cpp b/src/lua/functions/core/game/global_functions.cpp index 7d725b85bce..e2961e26215 100644 --- a/src/lua/functions/core/game/global_functions.cpp +++ b/src/lua/functions/core/game/global_functions.cpp @@ -741,16 +741,16 @@ int GlobalFunctions::luaDebugPrint(lua_State* L) { int GlobalFunctions::luaIsInWar(lua_State* L) { // isInWar(cid, target) - std::shared_ptr player = getPlayer(L, 1); + const auto &player = getPlayer(L, 1); if (!player) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + reportErrorFunc(fmt::format("{} - Player", getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND))); pushBoolean(L, false); return 1; } - std::shared_ptr targetPlayer = getPlayer(L, 2); + const auto &targetPlayer = getPlayer(L, 2); if (!targetPlayer) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + reportErrorFunc(fmt::format("{} - TargetPlayer", getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND))); pushBoolean(L, false); return 1; } diff --git a/src/lua/functions/core/game/modal_window_functions.cpp b/src/lua/functions/core/game/modal_window_functions.cpp index 11441993fa4..ee2cb7bd89f 100644 --- a/src/lua/functions/core/game/modal_window_functions.cpp +++ b/src/lua/functions/core/game/modal_window_functions.cpp @@ -204,9 +204,9 @@ int ModalWindowFunctions::luaModalWindowSetPriority(lua_State* L) { int ModalWindowFunctions::luaModalWindowSendToPlayer(lua_State* L) { // modalWindow:sendToPlayer(player) - std::shared_ptr player = getPlayer(L, 2); + const auto &player = getPlayer(L, 2); if (!player) { - lua_pushnil(L); + reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); return 1; } diff --git a/src/lua/functions/core/network/network_message_functions.cpp b/src/lua/functions/core/network/network_message_functions.cpp index a0f02631a1c..61567b1e1f0 100644 --- a/src/lua/functions/core/network/network_message_functions.cpp +++ b/src/lua/functions/core/network/network_message_functions.cpp @@ -289,12 +289,12 @@ int NetworkMessageFunctions::luaNetworkMessageSendToPlayer(lua_State* L) { } const auto &player = getPlayer(L, 2); - if (player) { - player->sendNetworkMessage(*message); - pushBoolean(L, true); - } else { + if (!player) { reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); - lua_pushnil(L); + return 1; } + + player->sendNetworkMessage(*message); + pushBoolean(L, true); return 1; } diff --git a/src/lua/functions/creatures/npc/npc_functions.cpp b/src/lua/functions/creatures/npc/npc_functions.cpp index e0ae3c2bfaf..d24ed978ac8 100644 --- a/src/lua/functions/creatures/npc/npc_functions.cpp +++ b/src/lua/functions/creatures/npc/npc_functions.cpp @@ -347,7 +347,7 @@ int NpcFunctions::luaNpcOpenShopWindow(lua_State* L) { return 1; } - std::shared_ptr player = getPlayer(L, 2); + const auto &player = getPlayer(L, 2); if (!player) { reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); pushBoolean(L, false); @@ -360,7 +360,7 @@ int NpcFunctions::luaNpcOpenShopWindow(lua_State* L) { int NpcFunctions::luaNpcCloseShopWindow(lua_State* L) { // npc:closeShopWindow(player) - std::shared_ptr player = getPlayer(L, 2); + const auto &player = getPlayer(L, 2); if (!player) { reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); pushBoolean(L, false); @@ -452,7 +452,13 @@ int NpcFunctions::luaNpcFollow(lua_State* L) { return 1; } - pushBoolean(L, npc->setFollowCreature(getPlayer(L, 2))); + const auto &player = getPlayer(L, 2); + if (!player) { + reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + return 1; + } + + pushBoolean(L, npc->setFollowCreature(player)); return 1; } @@ -478,7 +484,7 @@ int NpcFunctions::luaNpcSellItem(lua_State* L) { return 1; } - std::shared_ptr player = getPlayer(L, 2); + const auto &player = getPlayer(L, 2); if (!player) { reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); pushBoolean(L, false); diff --git a/src/lua/functions/creatures/player/party_functions.cpp b/src/lua/functions/creatures/player/party_functions.cpp index 6b5872d836e..e16499870a6 100644 --- a/src/lua/functions/creatures/player/party_functions.cpp +++ b/src/lua/functions/creatures/player/party_functions.cpp @@ -69,9 +69,14 @@ int PartyFunctions::luaPartyGetLeader(lua_State* L) { int PartyFunctions::luaPartySetLeader(lua_State* L) { // party:setLeader(player) - std::shared_ptr player = getPlayer(L, 2); + const auto &player = getPlayer(L, 2); + if (!player) { + reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + return 1; + } + std::shared_ptr party = getUserdataShared(L, 1); - if (party && player) { + if (party) { pushBoolean(L, party->passPartyLeadership(player)); } else { lua_pushnil(L); @@ -139,7 +144,12 @@ int PartyFunctions::luaPartyGetInviteeCount(lua_State* L) { int PartyFunctions::luaPartyAddInvite(lua_State* L) { // party:addInvite(player) - std::shared_ptr player = getPlayer(L, 2); + const auto &player = getPlayer(L, 2); + if (!player) { + reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + return 1; + } + std::shared_ptr party = getUserdataShared(L, 1); if (party && player) { pushBoolean(L, party->invitePlayer(player)); @@ -151,7 +161,12 @@ int PartyFunctions::luaPartyAddInvite(lua_State* L) { int PartyFunctions::luaPartyRemoveInvite(lua_State* L) { // party:removeInvite(player) - std::shared_ptr player = getPlayer(L, 2); + const auto &player = getPlayer(L, 2); + if (!player) { + reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + return 1; + } + std::shared_ptr party = getUserdataShared(L, 1); if (party && player) { pushBoolean(L, party->removeInvite(player)); @@ -163,7 +178,12 @@ int PartyFunctions::luaPartyRemoveInvite(lua_State* L) { int PartyFunctions::luaPartyAddMember(lua_State* L) { // party:addMember(player) - std::shared_ptr player = getPlayer(L, 2); + const auto &player = getPlayer(L, 2); + if (!player) { + reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + return 1; + } + std::shared_ptr party = getUserdataShared(L, 1); if (party && player) { pushBoolean(L, party->joinParty(player)); @@ -175,7 +195,12 @@ int PartyFunctions::luaPartyAddMember(lua_State* L) { int PartyFunctions::luaPartyRemoveMember(lua_State* L) { // party:removeMember(player) - std::shared_ptr player = getPlayer(L, 2); + const auto &player = getPlayer(L, 2); + if (!player) { + reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + return 1; + } + std::shared_ptr party = getUserdataShared(L, 1); if (party && player) { pushBoolean(L, party->leaveParty(player)); diff --git a/src/lua/functions/creatures/player/player_functions.cpp b/src/lua/functions/creatures/player/player_functions.cpp index f328f3369ef..5b646264d95 100644 --- a/src/lua/functions/creatures/player/player_functions.cpp +++ b/src/lua/functions/creatures/player/player_functions.cpp @@ -983,16 +983,17 @@ int PlayerFunctions::luaPlayerGetMaxMana(lua_State* L) { int PlayerFunctions::luaPlayerSetMaxMana(lua_State* L) { // player:setMaxMana(maxMana) - std::shared_ptr player = getPlayer(L, 1); - if (player) { - player->manaMax = getNumber(L, 2); - player->mana = std::min(player->mana, player->manaMax); - g_game().addPlayerMana(player); - player->sendStats(); - pushBoolean(L, true); - } else { - lua_pushnil(L); + const auto &player = getPlayer(L, 1); + if (!player) { + reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + return 1; } + + player->manaMax = getNumber(L, 2); + player->mana = std::min(player->mana, player->manaMax); + g_game().addPlayerMana(player); + player->sendStats(); + pushBoolean(L, true); return 1; } diff --git a/src/lua/functions/map/house_functions.cpp b/src/lua/functions/map/house_functions.cpp index e576b160323..834382ae432 100644 --- a/src/lua/functions/map/house_functions.cpp +++ b/src/lua/functions/map/house_functions.cpp @@ -368,7 +368,12 @@ int HouseFunctions::luaHouseCanEditAccessList(lua_State* L) { } uint32_t listId = getNumber(L, 2); - std::shared_ptr player = getPlayer(L, 3); + + const auto &player = getPlayer(L, 3); + if (!player) { + reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + return 1; + } pushBoolean(L, house->canEditAccessList(listId, player)); return 1; @@ -415,7 +420,19 @@ int HouseFunctions::luaHouseKickPlayer(lua_State* L) { return 1; } - pushBoolean(L, house->kickPlayer(getPlayer(L, 2), getPlayer(L, 3))); + const auto &player = getPlayer(L, 2); + if (!player) { + reportErrorFunc("Player is nullptr"); + return 1; + } + + auto targetPlayer = getPlayer(L, 3); + if (!targetPlayer) { + reportErrorFunc("Target player is nullptr"); + return 1; + } + + pushBoolean(L, house->kickPlayer(player, targetPlayer)); return 1; } @@ -427,9 +444,9 @@ int HouseFunctions::luaHouseIsInvited(lua_State* L) { return 1; } - std::shared_ptr player = getPlayer(L, 2); + const auto &player = getPlayer(L, 2); if (!player) { - lua_pushnil(L); + reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); return 1; } diff --git a/src/lua/functions/map/position_functions.cpp b/src/lua/functions/map/position_functions.cpp index f2d5b0e2873..b68d8501588 100644 --- a/src/lua/functions/map/position_functions.cpp +++ b/src/lua/functions/map/position_functions.cpp @@ -150,9 +150,13 @@ int PositionFunctions::luaPositionSendMagicEffect(lua_State* L) { // position:sendMagicEffect(magicEffect[, player = nullptr]) CreatureVector spectators; if (lua_gettop(L) >= 3) { - if (const auto &player = getPlayer(L, 3)) { - spectators.emplace_back(player); + const auto &player = getPlayer(L, 3); + if (!player) { + reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + return 1; } + + spectators.emplace_back(player); } MagicEffectClasses magicEffect = getNumber(L, 2); @@ -177,9 +181,13 @@ int PositionFunctions::luaPositionRemoveMagicEffect(lua_State* L) { // position:removeMagicEffect(magicEffect[, player = nullptr]) CreatureVector spectators; if (lua_gettop(L) >= 3) { - if (const auto &player = getPlayer(L, 3)) { - spectators.emplace_back(player); + const auto &player = getPlayer(L, 3); + if (!player) { + reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + return 1; } + + spectators.emplace_back(player); } MagicEffectClasses magicEffect = getNumber(L, 2); @@ -204,9 +212,13 @@ int PositionFunctions::luaPositionSendDistanceEffect(lua_State* L) { // position:sendDistanceEffect(positionEx, distanceEffect[, player = nullptr]) CreatureVector spectators; if (lua_gettop(L) >= 4) { - if (const auto &player = getPlayer(L, 4)) { - spectators.emplace_back(player); + const auto &player = getPlayer(L, 4); + if (!player) { + reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); + return 1; } + + spectators.emplace_back(player); } ShootType_t distanceEffect = getNumber(L, 3);